1 /* 2 * Copyright (C) 2015 ST Microelectronics 3 * 4 * Author: Lee Jones <lee.jones@linaro.org> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 */ 11 12 #include <linux/debugfs.h> 13 #include <linux/err.h> 14 #include <linux/io.h> 15 #include <linux/kernel.h> 16 #include <linux/mailbox_client.h> 17 #include <linux/module.h> 18 #include <linux/of.h> 19 #include <linux/platform_device.h> 20 #include <linux/slab.h> 21 #include <linux/uaccess.h> 22 23 #define MBOX_MAX_SIG_LEN 8 24 #define MBOX_MAX_MSG_LEN 128 25 #define MBOX_BYTES_PER_LINE 16 26 #define MBOX_HEXDUMP_LINE_LEN ((MBOX_BYTES_PER_LINE * 4) + 2) 27 #define MBOX_HEXDUMP_MAX_LEN (MBOX_HEXDUMP_LINE_LEN * \ 28 (MBOX_MAX_MSG_LEN / MBOX_BYTES_PER_LINE)) 29 30 static struct dentry *root_debugfs_dir; 31 32 struct mbox_test_device { 33 struct device *dev; 34 void __iomem *tx_mmio; 35 void __iomem *rx_mmio; 36 struct mbox_chan *tx_channel; 37 struct mbox_chan *rx_channel; 38 char *rx_buffer; 39 char *signal; 40 char *message; 41 spinlock_t lock; 42 }; 43 44 static ssize_t mbox_test_signal_write(struct file *filp, 45 const char __user *userbuf, 46 size_t count, loff_t *ppos) 47 { 48 struct mbox_test_device *tdev = filp->private_data; 49 int ret; 50 51 if (!tdev->tx_channel) { 52 dev_err(tdev->dev, "Channel cannot do Tx\n"); 53 return -EINVAL; 54 } 55 56 if (count > MBOX_MAX_SIG_LEN) { 57 dev_err(tdev->dev, 58 "Signal length %zd greater than max allowed %d\n", 59 count, MBOX_MAX_SIG_LEN); 60 return -EINVAL; 61 } 62 63 tdev->signal = kzalloc(MBOX_MAX_SIG_LEN, GFP_KERNEL); 64 if (!tdev->signal) 65 return -ENOMEM; 66 67 ret = copy_from_user(tdev->signal, userbuf, count); 68 if (ret) { 69 kfree(tdev->signal); 70 return -EFAULT; 71 } 72 73 return ret < 0 ? ret : count; 74 } 75 76 static const struct file_operations mbox_test_signal_ops = { 77 .write = mbox_test_signal_write, 78 .open = simple_open, 79 .llseek = generic_file_llseek, 80 }; 81 82 static ssize_t mbox_test_message_write(struct file *filp, 83 const char __user *userbuf, 84 size_t count, loff_t *ppos) 85 { 86 struct mbox_test_device *tdev = filp->private_data; 87 void *data; 88 int ret; 89 90 if (!tdev->tx_channel) { 91 dev_err(tdev->dev, "Channel cannot do Tx\n"); 92 return -EINVAL; 93 } 94 95 if (count > MBOX_MAX_MSG_LEN) { 96 dev_err(tdev->dev, 97 "Message length %zd greater than max allowed %d\n", 98 count, MBOX_MAX_MSG_LEN); 99 return -EINVAL; 100 } 101 102 tdev->message = kzalloc(MBOX_MAX_MSG_LEN, GFP_KERNEL); 103 if (!tdev->message) 104 return -ENOMEM; 105 106 ret = copy_from_user(tdev->message, userbuf, count); 107 if (ret) { 108 ret = -EFAULT; 109 goto out; 110 } 111 112 /* 113 * A separate signal is only of use if there is 114 * MMIO to subsequently pass the message through 115 */ 116 if (tdev->tx_mmio && tdev->signal) { 117 print_hex_dump_bytes("Client: Sending: Signal: ", DUMP_PREFIX_ADDRESS, 118 tdev->signal, MBOX_MAX_SIG_LEN); 119 120 data = tdev->signal; 121 } else 122 data = tdev->message; 123 124 print_hex_dump_bytes("Client: Sending: Message: ", DUMP_PREFIX_ADDRESS, 125 tdev->message, MBOX_MAX_MSG_LEN); 126 127 ret = mbox_send_message(tdev->tx_channel, data); 128 if (ret < 0) 129 dev_err(tdev->dev, "Failed to send message via mailbox\n"); 130 131 out: 132 kfree(tdev->signal); 133 kfree(tdev->message); 134 135 return ret < 0 ? ret : count; 136 } 137 138 static ssize_t mbox_test_message_read(struct file *filp, char __user *userbuf, 139 size_t count, loff_t *ppos) 140 { 141 struct mbox_test_device *tdev = filp->private_data; 142 unsigned long flags; 143 char *touser, *ptr; 144 int l = 0; 145 int ret; 146 147 touser = kzalloc(MBOX_HEXDUMP_MAX_LEN + 1, GFP_KERNEL); 148 if (!touser) 149 return -ENOMEM; 150 151 if (!tdev->rx_channel) { 152 ret = snprintf(touser, 20, "<NO RX CAPABILITY>\n"); 153 ret = simple_read_from_buffer(userbuf, count, ppos, 154 touser, ret); 155 goto out; 156 } 157 158 if (tdev->rx_buffer[0] == '\0') { 159 ret = snprintf(touser, 9, "<EMPTY>\n"); 160 ret = simple_read_from_buffer(userbuf, count, ppos, 161 touser, ret); 162 goto out; 163 } 164 165 spin_lock_irqsave(&tdev->lock, flags); 166 167 ptr = tdev->rx_buffer; 168 while (l < MBOX_HEXDUMP_MAX_LEN) { 169 hex_dump_to_buffer(ptr, 170 MBOX_BYTES_PER_LINE, 171 MBOX_BYTES_PER_LINE, 1, touser + l, 172 MBOX_HEXDUMP_LINE_LEN, true); 173 174 ptr += MBOX_BYTES_PER_LINE; 175 l += MBOX_HEXDUMP_LINE_LEN; 176 *(touser + (l - 1)) = '\n'; 177 } 178 *(touser + l) = '\0'; 179 180 memset(tdev->rx_buffer, 0, MBOX_MAX_MSG_LEN); 181 182 spin_unlock_irqrestore(&tdev->lock, flags); 183 184 ret = simple_read_from_buffer(userbuf, count, ppos, touser, MBOX_HEXDUMP_MAX_LEN); 185 out: 186 kfree(touser); 187 return ret; 188 } 189 190 static const struct file_operations mbox_test_message_ops = { 191 .write = mbox_test_message_write, 192 .read = mbox_test_message_read, 193 .open = simple_open, 194 .llseek = generic_file_llseek, 195 }; 196 197 static int mbox_test_add_debugfs(struct platform_device *pdev, 198 struct mbox_test_device *tdev) 199 { 200 if (!debugfs_initialized()) 201 return 0; 202 203 root_debugfs_dir = debugfs_create_dir("mailbox", NULL); 204 if (!root_debugfs_dir) { 205 dev_err(&pdev->dev, "Failed to create Mailbox debugfs\n"); 206 return -EINVAL; 207 } 208 209 debugfs_create_file("message", 0600, root_debugfs_dir, 210 tdev, &mbox_test_message_ops); 211 212 debugfs_create_file("signal", 0200, root_debugfs_dir, 213 tdev, &mbox_test_signal_ops); 214 215 return 0; 216 } 217 218 static void mbox_test_receive_message(struct mbox_client *client, void *message) 219 { 220 struct mbox_test_device *tdev = dev_get_drvdata(client->dev); 221 unsigned long flags; 222 223 spin_lock_irqsave(&tdev->lock, flags); 224 if (tdev->rx_mmio) { 225 memcpy_fromio(tdev->rx_buffer, tdev->rx_mmio, MBOX_MAX_MSG_LEN); 226 print_hex_dump_bytes("Client: Received [MMIO]: ", DUMP_PREFIX_ADDRESS, 227 tdev->rx_buffer, MBOX_MAX_MSG_LEN); 228 } else if (message) { 229 print_hex_dump_bytes("Client: Received [API]: ", DUMP_PREFIX_ADDRESS, 230 message, MBOX_MAX_MSG_LEN); 231 memcpy(tdev->rx_buffer, message, MBOX_MAX_MSG_LEN); 232 } 233 spin_unlock_irqrestore(&tdev->lock, flags); 234 } 235 236 static void mbox_test_prepare_message(struct mbox_client *client, void *message) 237 { 238 struct mbox_test_device *tdev = dev_get_drvdata(client->dev); 239 240 if (tdev->tx_mmio) { 241 if (tdev->signal) 242 memcpy_toio(tdev->tx_mmio, tdev->message, MBOX_MAX_MSG_LEN); 243 else 244 memcpy_toio(tdev->tx_mmio, message, MBOX_MAX_MSG_LEN); 245 } 246 } 247 248 static void mbox_test_message_sent(struct mbox_client *client, 249 void *message, int r) 250 { 251 if (r) 252 dev_warn(client->dev, 253 "Client: Message could not be sent: %d\n", r); 254 else 255 dev_info(client->dev, 256 "Client: Message sent\n"); 257 } 258 259 static struct mbox_chan * 260 mbox_test_request_channel(struct platform_device *pdev, const char *name) 261 { 262 struct mbox_client *client; 263 struct mbox_chan *channel; 264 265 client = devm_kzalloc(&pdev->dev, sizeof(*client), GFP_KERNEL); 266 if (!client) 267 return ERR_PTR(-ENOMEM); 268 269 client->dev = &pdev->dev; 270 client->rx_callback = mbox_test_receive_message; 271 client->tx_prepare = mbox_test_prepare_message; 272 client->tx_done = mbox_test_message_sent; 273 client->tx_block = true; 274 client->knows_txdone = false; 275 client->tx_tout = 500; 276 277 channel = mbox_request_channel_byname(client, name); 278 if (IS_ERR(channel)) { 279 dev_warn(&pdev->dev, "Failed to request %s channel\n", name); 280 return NULL; 281 } 282 283 return channel; 284 } 285 286 static int mbox_test_probe(struct platform_device *pdev) 287 { 288 struct mbox_test_device *tdev; 289 struct resource *res; 290 int ret; 291 292 tdev = devm_kzalloc(&pdev->dev, sizeof(*tdev), GFP_KERNEL); 293 if (!tdev) 294 return -ENOMEM; 295 296 /* It's okay for MMIO to be NULL */ 297 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 298 tdev->tx_mmio = devm_ioremap_resource(&pdev->dev, res); 299 if (IS_ERR(tdev->tx_mmio)) 300 tdev->tx_mmio = NULL; 301 302 /* If specified, second reg entry is Rx MMIO */ 303 res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 304 tdev->rx_mmio = devm_ioremap_resource(&pdev->dev, res); 305 if (IS_ERR(tdev->rx_mmio)) 306 tdev->rx_mmio = tdev->tx_mmio; 307 308 tdev->tx_channel = mbox_test_request_channel(pdev, "tx"); 309 tdev->rx_channel = mbox_test_request_channel(pdev, "rx"); 310 311 if (!tdev->tx_channel && !tdev->rx_channel) 312 return -EPROBE_DEFER; 313 314 /* If Rx is not specified but has Rx MMIO, then Rx = Tx */ 315 if (!tdev->rx_channel && (tdev->rx_mmio != tdev->tx_mmio)) 316 tdev->rx_channel = tdev->tx_channel; 317 318 tdev->dev = &pdev->dev; 319 platform_set_drvdata(pdev, tdev); 320 321 spin_lock_init(&tdev->lock); 322 323 if (tdev->rx_channel) { 324 tdev->rx_buffer = devm_kzalloc(&pdev->dev, 325 MBOX_MAX_MSG_LEN, GFP_KERNEL); 326 if (!tdev->rx_buffer) 327 return -ENOMEM; 328 } 329 330 ret = mbox_test_add_debugfs(pdev, tdev); 331 if (ret) 332 return ret; 333 334 dev_info(&pdev->dev, "Successfully registered\n"); 335 336 return 0; 337 } 338 339 static int mbox_test_remove(struct platform_device *pdev) 340 { 341 struct mbox_test_device *tdev = platform_get_drvdata(pdev); 342 343 debugfs_remove_recursive(root_debugfs_dir); 344 345 if (tdev->tx_channel) 346 mbox_free_channel(tdev->tx_channel); 347 if (tdev->rx_channel) 348 mbox_free_channel(tdev->rx_channel); 349 350 return 0; 351 } 352 353 static const struct of_device_id mbox_test_match[] = { 354 { .compatible = "mailbox-test" }, 355 {}, 356 }; 357 358 static struct platform_driver mbox_test_driver = { 359 .driver = { 360 .name = "mailbox_test", 361 .of_match_table = mbox_test_match, 362 }, 363 .probe = mbox_test_probe, 364 .remove = mbox_test_remove, 365 }; 366 module_platform_driver(mbox_test_driver); 367 368 MODULE_DESCRIPTION("Generic Mailbox Testing Facility"); 369 MODULE_AUTHOR("Lee Jones <lee.jones@linaro.org"); 370 MODULE_LICENSE("GPL v2"); 371