2874c5fd28426 (Thomas Gleixner 2019-05-27 08:55:01 +0200 1) // SPDX-License-Identifier: GPL-2.0-or-later
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 2) /*
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 3) * Copyright (C) 2015 ST Microelectronics
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 4) *
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 5) * Author: Lee Jones <lee.jones@linaro.org>
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 6) */
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 7)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 8) #include <linux/debugfs.h>
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 9) #include <linux/err.h>
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 10) #include <linux/fs.h>
a133f8b65d591 (Lee Jones 2015-10-20 17:11:27 +0100 11) #include <linux/io.h>
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 12) #include <linux/kernel.h>
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 13) #include <linux/mailbox_client.h>
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 14) #include <linux/module.h>
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 15) #include <linux/of.h>
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 16) #include <linux/platform_device.h>
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 17) #include <linux/poll.h>
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 18) #include <linux/slab.h>
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 19) #include <linux/uaccess.h>
174cd4b1e5fbd (Ingo Molnar 2017-02-02 19:15:33 +0100 20) #include <linux/sched/signal.h>
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 21)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 22) #define MBOX_MAX_SIG_LEN 8
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 23) #define MBOX_MAX_MSG_LEN 128
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 24) #define MBOX_BYTES_PER_LINE 16
6c03663f98b91 (Lee Jones 2015-10-16 13:32:47 +0100 25) #define MBOX_HEXDUMP_LINE_LEN ((MBOX_BYTES_PER_LINE * 4) + 2)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 26) #define MBOX_HEXDUMP_MAX_LEN (MBOX_HEXDUMP_LINE_LEN * \
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 27) (MBOX_MAX_MSG_LEN / MBOX_BYTES_PER_LINE))
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 28)
e339c80af95e1 (Sudeep Holla 2017-09-28 11:18:53 +0100 29) static bool mbox_data_ready;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 30)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 31) struct mbox_test_device {
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 32) struct device *dev;
2d74ffdc910e0 (Sudeep Holla 2016-02-19 16:01:18 +0000 33) void __iomem *tx_mmio;
2d74ffdc910e0 (Sudeep Holla 2016-02-19 16:01:18 +0000 34) void __iomem *rx_mmio;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 35) struct mbox_chan *tx_channel;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 36) struct mbox_chan *rx_channel;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 37) char *rx_buffer;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 38) char *signal;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 39) char *message;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 40) spinlock_t lock;
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 41) wait_queue_head_t waitq;
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 42) struct fasync_struct *async_queue;
10cfc5a92e36b (Fabien Dessenne 2019-01-04 14:47:15 +0100 43) struct dentry *root_debugfs_dir;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 44) };
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 45)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 46) static ssize_t mbox_test_signal_write(struct file *filp,
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 47) const char __user *userbuf,
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 48) size_t count, loff_t *ppos)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 49) {
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 50) struct mbox_test_device *tdev = filp->private_data;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 51)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 52) if (!tdev->tx_channel) {
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 53) dev_err(tdev->dev, "Channel cannot do Tx\n");
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 54) return -EINVAL;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 55) }
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 56)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 57) if (count > MBOX_MAX_SIG_LEN) {
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 58) dev_err(tdev->dev,
6c03663f98b91 (Lee Jones 2015-10-16 13:32:47 +0100 59) "Signal length %zd greater than max allowed %d\n",
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 60) count, MBOX_MAX_SIG_LEN);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 61) return -EINVAL;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 62) }
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 63)
d1c2f87c9a8f7 (Lee Jones 2016-03-23 14:43:42 +0000 64) /* Only allocate memory if we need to */
d1c2f87c9a8f7 (Lee Jones 2016-03-23 14:43:42 +0000 65) if (!tdev->signal) {
d1c2f87c9a8f7 (Lee Jones 2016-03-23 14:43:42 +0000 66) tdev->signal = kzalloc(MBOX_MAX_SIG_LEN, GFP_KERNEL);
d1c2f87c9a8f7 (Lee Jones 2016-03-23 14:43:42 +0000 67) if (!tdev->signal)
d1c2f87c9a8f7 (Lee Jones 2016-03-23 14:43:42 +0000 68) return -ENOMEM;
d1c2f87c9a8f7 (Lee Jones 2016-03-23 14:43:42 +0000 69) }
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 70)
17f5f28ffa6e8 (Lee Jones 2016-03-23 14:43:41 +0000 71) if (copy_from_user(tdev->signal, userbuf, count)) {
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 72) kfree(tdev->signal);
17f5f28ffa6e8 (Lee Jones 2016-03-23 14:43:41 +0000 73) tdev->signal = NULL;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 74) return -EFAULT;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 75) }
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 76)
17f5f28ffa6e8 (Lee Jones 2016-03-23 14:43:41 +0000 77) return count;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 78) }
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 79)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 80) static const struct file_operations mbox_test_signal_ops = {
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 81) .write = mbox_test_signal_write,
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 82) .open = simple_open,
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 83) .llseek = generic_file_llseek,
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 84) };
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 85)
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 86) static int mbox_test_message_fasync(int fd, struct file *filp, int on)
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 87) {
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 88) struct mbox_test_device *tdev = filp->private_data;
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 89)
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 90) return fasync_helper(fd, filp, on, &tdev->async_queue);
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 91) }
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 92)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 93) static ssize_t mbox_test_message_write(struct file *filp,
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 94) const char __user *userbuf,
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 95) size_t count, loff_t *ppos)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 96) {
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 97) struct mbox_test_device *tdev = filp->private_data;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 98) void *data;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 99) int ret;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 100)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 101) if (!tdev->tx_channel) {
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 102) dev_err(tdev->dev, "Channel cannot do Tx\n");
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 103) return -EINVAL;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 104) }
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 105)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 106) if (count > MBOX_MAX_MSG_LEN) {
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 107) dev_err(tdev->dev,
6c03663f98b91 (Lee Jones 2015-10-16 13:32:47 +0100 108) "Message length %zd greater than max allowed %d\n",
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 109) count, MBOX_MAX_MSG_LEN);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 110) return -EINVAL;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 111) }
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 112)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 113) tdev->message = kzalloc(MBOX_MAX_MSG_LEN, GFP_KERNEL);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 114) if (!tdev->message)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 115) return -ENOMEM;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 116)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 117) ret = copy_from_user(tdev->message, userbuf, count);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 118) if (ret) {
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 119) ret = -EFAULT;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 120) goto out;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 121) }
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 122)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 123) /*
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 124) * A separate signal is only of use if there is
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 125) * MMIO to subsequently pass the message through
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 126) */
2d74ffdc910e0 (Sudeep Holla 2016-02-19 16:01:18 +0000 127) if (tdev->tx_mmio && tdev->signal) {
27fa680f7f414 (Sudeep Holla 2016-02-19 16:01:17 +0000 128) print_hex_dump_bytes("Client: Sending: Signal: ", DUMP_PREFIX_ADDRESS,
27fa680f7f414 (Sudeep Holla 2016-02-19 16:01:17 +0000 129) tdev->signal, MBOX_MAX_SIG_LEN);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 130)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 131) data = tdev->signal;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 132) } else
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 133) data = tdev->message;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 134)
27fa680f7f414 (Sudeep Holla 2016-02-19 16:01:17 +0000 135) print_hex_dump_bytes("Client: Sending: Message: ", DUMP_PREFIX_ADDRESS,
27fa680f7f414 (Sudeep Holla 2016-02-19 16:01:17 +0000 136) tdev->message, MBOX_MAX_MSG_LEN);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 137)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 138) ret = mbox_send_message(tdev->tx_channel, data);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 139) if (ret < 0)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 140) dev_err(tdev->dev, "Failed to send message via mailbox\n");
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 141)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 142) out:
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 143) kfree(tdev->signal);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 144) kfree(tdev->message);
9ef3c5112139c (Sudeep Holla 2016-05-24 17:12:04 +0100 145) tdev->signal = NULL;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 146)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 147) return ret < 0 ? ret : count;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 148) }
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 149)
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 150) static bool mbox_test_message_data_ready(struct mbox_test_device *tdev)
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 151) {
e339c80af95e1 (Sudeep Holla 2017-09-28 11:18:53 +0100 152) bool data_ready;
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 153) unsigned long flags;
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 154)
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 155) spin_lock_irqsave(&tdev->lock, flags);
e339c80af95e1 (Sudeep Holla 2017-09-28 11:18:53 +0100 156) data_ready = mbox_data_ready;
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 157) spin_unlock_irqrestore(&tdev->lock, flags);
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 158)
e339c80af95e1 (Sudeep Holla 2017-09-28 11:18:53 +0100 159) return data_ready;
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 160) }
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 161)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 162) static ssize_t mbox_test_message_read(struct file *filp, char __user *userbuf,
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 163) size_t count, loff_t *ppos)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 164) {
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 165) struct mbox_test_device *tdev = filp->private_data;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 166) unsigned long flags;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 167) char *touser, *ptr;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 168) int l = 0;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 169) int ret;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 170)
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 171) DECLARE_WAITQUEUE(wait, current);
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 172)
c3ac54a6f5544 (Dan Carpenter 2015-10-22 22:51:27 +0300 173) touser = kzalloc(MBOX_HEXDUMP_MAX_LEN + 1, GFP_KERNEL);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 174) if (!touser)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 175) return -ENOMEM;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 176)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 177) if (!tdev->rx_channel) {
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 178) ret = snprintf(touser, 20, "<NO RX CAPABILITY>\n");
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 179) ret = simple_read_from_buffer(userbuf, count, ppos,
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 180) touser, ret);
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 181) goto kfree_err;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 182) }
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 183)
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 184) add_wait_queue(&tdev->waitq, &wait);
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 185)
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 186) do {
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 187) __set_current_state(TASK_INTERRUPTIBLE);
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 188)
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 189) if (mbox_test_message_data_ready(tdev))
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 190) break;
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 191)
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 192) if (filp->f_flags & O_NONBLOCK) {
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 193) ret = -EAGAIN;
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 194) goto waitq_err;
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 195) }
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 196)
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 197) if (signal_pending(current)) {
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 198) ret = -ERESTARTSYS;
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 199) goto waitq_err;
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 200) }
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 201) schedule();
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 202)
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 203) } while (1);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 204)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 205) spin_lock_irqsave(&tdev->lock, flags);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 206)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 207) ptr = tdev->rx_buffer;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 208) while (l < MBOX_HEXDUMP_MAX_LEN) {
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 209) hex_dump_to_buffer(ptr,
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 210) MBOX_BYTES_PER_LINE,
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 211) MBOX_BYTES_PER_LINE, 1, touser + l,
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 212) MBOX_HEXDUMP_LINE_LEN, true);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 213)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 214) ptr += MBOX_BYTES_PER_LINE;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 215) l += MBOX_HEXDUMP_LINE_LEN;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 216) *(touser + (l - 1)) = '\n';
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 217) }
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 218) *(touser + l) = '\0';
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 219)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 220) memset(tdev->rx_buffer, 0, MBOX_MAX_MSG_LEN);
e339c80af95e1 (Sudeep Holla 2017-09-28 11:18:53 +0100 221) mbox_data_ready = false;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 222)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 223) spin_unlock_irqrestore(&tdev->lock, flags);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 224)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 225) ret = simple_read_from_buffer(userbuf, count, ppos, touser, MBOX_HEXDUMP_MAX_LEN);
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 226) waitq_err:
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 227) __set_current_state(TASK_RUNNING);
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 228) remove_wait_queue(&tdev->waitq, &wait);
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 229) kfree_err:
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 230) kfree(touser);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 231) return ret;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 232) }
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 233)
afc9a42b7464f (Al Viro 2017-07-03 06:39:46 -0400 234) static __poll_t
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 235) mbox_test_message_poll(struct file *filp, struct poll_table_struct *wait)
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 236) {
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 237) struct mbox_test_device *tdev = filp->private_data;
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 238)
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 239) poll_wait(filp, &tdev->waitq, wait);
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 240)
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 241) if (mbox_test_message_data_ready(tdev))
a9a08845e9acb (Linus Torvalds 2018-02-11 14:34:03 -0800 242) return EPOLLIN | EPOLLRDNORM;
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 243) return 0;
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 244) }
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 245)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 246) static const struct file_operations mbox_test_message_ops = {
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 247) .write = mbox_test_message_write,
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 248) .read = mbox_test_message_read,
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 249) .fasync = mbox_test_message_fasync,
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 250) .poll = mbox_test_message_poll,
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 251) .open = simple_open,
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 252) .llseek = generic_file_llseek,
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 253) };
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 254)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 255) static int mbox_test_add_debugfs(struct platform_device *pdev,
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 256) struct mbox_test_device *tdev)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 257) {
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 258) if (!debugfs_initialized())
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 259) return 0;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 260)
10cfc5a92e36b (Fabien Dessenne 2019-01-04 14:47:15 +0100 261) tdev->root_debugfs_dir = debugfs_create_dir(dev_name(&pdev->dev), NULL);
10cfc5a92e36b (Fabien Dessenne 2019-01-04 14:47:15 +0100 262) if (!tdev->root_debugfs_dir) {
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 263) dev_err(&pdev->dev, "Failed to create Mailbox debugfs\n");
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 264) return -EINVAL;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 265) }
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 266)
10cfc5a92e36b (Fabien Dessenne 2019-01-04 14:47:15 +0100 267) debugfs_create_file("message", 0600, tdev->root_debugfs_dir,
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 268) tdev, &mbox_test_message_ops);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 269)
10cfc5a92e36b (Fabien Dessenne 2019-01-04 14:47:15 +0100 270) debugfs_create_file("signal", 0200, tdev->root_debugfs_dir,
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 271) tdev, &mbox_test_signal_ops);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 272)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 273) return 0;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 274) }
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 275)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 276) static void mbox_test_receive_message(struct mbox_client *client, void *message)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 277) {
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 278) struct mbox_test_device *tdev = dev_get_drvdata(client->dev);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 279) unsigned long flags;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 280)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 281) spin_lock_irqsave(&tdev->lock, flags);
2d74ffdc910e0 (Sudeep Holla 2016-02-19 16:01:18 +0000 282) if (tdev->rx_mmio) {
2d74ffdc910e0 (Sudeep Holla 2016-02-19 16:01:18 +0000 283) memcpy_fromio(tdev->rx_buffer, tdev->rx_mmio, MBOX_MAX_MSG_LEN);
27fa680f7f414 (Sudeep Holla 2016-02-19 16:01:17 +0000 284) print_hex_dump_bytes("Client: Received [MMIO]: ", DUMP_PREFIX_ADDRESS,
27fa680f7f414 (Sudeep Holla 2016-02-19 16:01:17 +0000 285) tdev->rx_buffer, MBOX_MAX_MSG_LEN);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 286) } else if (message) {
27fa680f7f414 (Sudeep Holla 2016-02-19 16:01:17 +0000 287) print_hex_dump_bytes("Client: Received [API]: ", DUMP_PREFIX_ADDRESS,
27fa680f7f414 (Sudeep Holla 2016-02-19 16:01:17 +0000 288) message, MBOX_MAX_MSG_LEN);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 289) memcpy(tdev->rx_buffer, message, MBOX_MAX_MSG_LEN);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 290) }
e339c80af95e1 (Sudeep Holla 2017-09-28 11:18:53 +0100 291) mbox_data_ready = true;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 292) spin_unlock_irqrestore(&tdev->lock, flags);
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 293)
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 294) wake_up_interruptible(&tdev->waitq);
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 295)
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 296) kill_fasync(&tdev->async_queue, SIGIO, POLL_IN);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 297) }
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 298)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 299) static void mbox_test_prepare_message(struct mbox_client *client, void *message)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 300) {
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 301) struct mbox_test_device *tdev = dev_get_drvdata(client->dev);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 302)
2d74ffdc910e0 (Sudeep Holla 2016-02-19 16:01:18 +0000 303) if (tdev->tx_mmio) {
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 304) if (tdev->signal)
2d74ffdc910e0 (Sudeep Holla 2016-02-19 16:01:18 +0000 305) memcpy_toio(tdev->tx_mmio, tdev->message, MBOX_MAX_MSG_LEN);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 306) else
2d74ffdc910e0 (Sudeep Holla 2016-02-19 16:01:18 +0000 307) memcpy_toio(tdev->tx_mmio, message, MBOX_MAX_MSG_LEN);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 308) }
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 309) }
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 310)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 311) static void mbox_test_message_sent(struct mbox_client *client,
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 312) void *message, int r)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 313) {
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 314) if (r)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 315) dev_warn(client->dev,
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 316) "Client: Message could not be sent: %d\n", r);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 317) else
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 318) dev_info(client->dev,
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 319) "Client: Message sent\n");
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 320) }
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 321)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 322) static struct mbox_chan *
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 323) mbox_test_request_channel(struct platform_device *pdev, const char *name)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 324) {
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 325) struct mbox_client *client;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 326) struct mbox_chan *channel;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 327)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 328) client = devm_kzalloc(&pdev->dev, sizeof(*client), GFP_KERNEL);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 329) if (!client)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 330) return ERR_PTR(-ENOMEM);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 331)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 332) client->dev = &pdev->dev;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 333) client->rx_callback = mbox_test_receive_message;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 334) client->tx_prepare = mbox_test_prepare_message;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 335) client->tx_done = mbox_test_message_sent;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 336) client->tx_block = true;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 337) client->knows_txdone = false;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 338) client->tx_tout = 500;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 339)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 340) channel = mbox_request_channel_byname(client, name);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 341) if (IS_ERR(channel)) {
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 342) dev_warn(&pdev->dev, "Failed to request %s channel\n", name);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 343) return NULL;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 344) }
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 345)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 346) return channel;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 347) }
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 348)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 349) static int mbox_test_probe(struct platform_device *pdev)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 350) {
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 351) struct mbox_test_device *tdev;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 352) struct resource *res;
db4d22c07e3e6 (Sudeep Holla 2016-11-29 14:37:05 +0000 353) resource_size_t size;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 354) int ret;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 355)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 356) tdev = devm_kzalloc(&pdev->dev, sizeof(*tdev), GFP_KERNEL);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 357) if (!tdev)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 358) return -ENOMEM;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 359)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 360) /* It's okay for MMIO to be NULL */
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 361) res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2d74ffdc910e0 (Sudeep Holla 2016-02-19 16:01:18 +0000 362) tdev->tx_mmio = devm_ioremap_resource(&pdev->dev, res);
6899b4f7c99c7 (Fabien Dessenne 2019-01-04 14:47:16 +0100 363) if (PTR_ERR(tdev->tx_mmio) == -EBUSY) {
db4d22c07e3e6 (Sudeep Holla 2016-11-29 14:37:05 +0000 364) /* if reserved area in SRAM, try just ioremap */
6899b4f7c99c7 (Fabien Dessenne 2019-01-04 14:47:16 +0100 365) size = resource_size(res);
db4d22c07e3e6 (Sudeep Holla 2016-11-29 14:37:05 +0000 366) tdev->tx_mmio = devm_ioremap(&pdev->dev, res->start, size);
6899b4f7c99c7 (Fabien Dessenne 2019-01-04 14:47:16 +0100 367) } else if (IS_ERR(tdev->tx_mmio)) {
2d74ffdc910e0 (Sudeep Holla 2016-02-19 16:01:18 +0000 368) tdev->tx_mmio = NULL;
6899b4f7c99c7 (Fabien Dessenne 2019-01-04 14:47:16 +0100 369) }
2d74ffdc910e0 (Sudeep Holla 2016-02-19 16:01:18 +0000 370)
2d74ffdc910e0 (Sudeep Holla 2016-02-19 16:01:18 +0000 371) /* If specified, second reg entry is Rx MMIO */
2d74ffdc910e0 (Sudeep Holla 2016-02-19 16:01:18 +0000 372) res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
2d74ffdc910e0 (Sudeep Holla 2016-02-19 16:01:18 +0000 373) tdev->rx_mmio = devm_ioremap_resource(&pdev->dev, res);
6899b4f7c99c7 (Fabien Dessenne 2019-01-04 14:47:16 +0100 374) if (PTR_ERR(tdev->rx_mmio) == -EBUSY) {
6899b4f7c99c7 (Fabien Dessenne 2019-01-04 14:47:16 +0100 375) size = resource_size(res);
db4d22c07e3e6 (Sudeep Holla 2016-11-29 14:37:05 +0000 376) tdev->rx_mmio = devm_ioremap(&pdev->dev, res->start, size);
6899b4f7c99c7 (Fabien Dessenne 2019-01-04 14:47:16 +0100 377) } else if (IS_ERR(tdev->rx_mmio)) {
2d74ffdc910e0 (Sudeep Holla 2016-02-19 16:01:18 +0000 378) tdev->rx_mmio = tdev->tx_mmio;
6899b4f7c99c7 (Fabien Dessenne 2019-01-04 14:47:16 +0100 379) }
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 380)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 381) tdev->tx_channel = mbox_test_request_channel(pdev, "tx");
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 382) tdev->rx_channel = mbox_test_request_channel(pdev, "rx");
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 383)
6c03663f98b91 (Lee Jones 2015-10-16 13:32:47 +0100 384) if (!tdev->tx_channel && !tdev->rx_channel)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 385) return -EPROBE_DEFER;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 386)
2d74ffdc910e0 (Sudeep Holla 2016-02-19 16:01:18 +0000 387) /* If Rx is not specified but has Rx MMIO, then Rx = Tx */
2d74ffdc910e0 (Sudeep Holla 2016-02-19 16:01:18 +0000 388) if (!tdev->rx_channel && (tdev->rx_mmio != tdev->tx_mmio))
2d74ffdc910e0 (Sudeep Holla 2016-02-19 16:01:18 +0000 389) tdev->rx_channel = tdev->tx_channel;
2d74ffdc910e0 (Sudeep Holla 2016-02-19 16:01:18 +0000 390)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 391) tdev->dev = &pdev->dev;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 392) platform_set_drvdata(pdev, tdev);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 393)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 394) spin_lock_init(&tdev->lock);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 395)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 396) if (tdev->rx_channel) {
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 397) tdev->rx_buffer = devm_kzalloc(&pdev->dev,
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 398) MBOX_MAX_MSG_LEN, GFP_KERNEL);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 399) if (!tdev->rx_buffer)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 400) return -ENOMEM;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 401) }
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 402)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 403) ret = mbox_test_add_debugfs(pdev, tdev);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 404) if (ret)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 405) return ret;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 406)
baef9a35d2462 (Sudeep Holla 2016-11-29 14:37:04 +0000 407) init_waitqueue_head(&tdev->waitq);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 408) dev_info(&pdev->dev, "Successfully registered\n");
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 409)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 410) return 0;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 411) }
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 412)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 413) static int mbox_test_remove(struct platform_device *pdev)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 414) {
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 415) struct mbox_test_device *tdev = platform_get_drvdata(pdev);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 416)
10cfc5a92e36b (Fabien Dessenne 2019-01-04 14:47:15 +0100 417) debugfs_remove_recursive(tdev->root_debugfs_dir);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 418)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 419) if (tdev->tx_channel)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 420) mbox_free_channel(tdev->tx_channel);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 421) if (tdev->rx_channel)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 422) mbox_free_channel(tdev->rx_channel);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 423)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 424) return 0;
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 425) }
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 426)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 427) static const struct of_device_id mbox_test_match[] = {
c428013783dc9 (Sudeep Holla 2016-02-19 16:01:16 +0000 428) { .compatible = "mailbox-test" },
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 429) {},
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 430) };
f42cce3c24099 (Javier Martinez Canillas 2016-10-20 00:34:04 -0300 431) MODULE_DEVICE_TABLE(of, mbox_test_match);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 432)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 433) static struct platform_driver mbox_test_driver = {
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 434) .driver = {
adf06ba9b363c (Sudeep Holla 2016-02-19 16:01:15 +0000 435) .name = "mailbox_test",
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 436) .of_match_table = mbox_test_match,
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 437) },
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 438) .probe = mbox_test_probe,
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 439) .remove = mbox_test_remove,
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 440) };
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 441) module_platform_driver(mbox_test_driver);
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 442)
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 443) MODULE_DESCRIPTION("Generic Mailbox Testing Facility");
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 444) MODULE_AUTHOR("Lee Jones <lee.jones@linaro.org");
8ea4484d0c2bb (Lee Jones 2015-10-16 08:21:30 +0100 445) MODULE_LICENSE("GPL v2");