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