VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   33 Branches   57 Tags
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");