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 tdev->signal = NULL; 137 138 return ret < 0 ? ret : count; 139 } 140 141 static ssize_t mbox_test_message_read(struct file *filp, char __user *userbuf, 142 size_t count, loff_t *ppos) 143 { 144 struct mbox_test_device *tdev = filp->private_data; 145 unsigned long flags; 146 char *touser, *ptr; 147 int l = 0; 148 int ret; 149 150 touser = kzalloc(MBOX_HEXDUMP_MAX_LEN + 1, GFP_KERNEL); 151 if (!touser) 152 return -ENOMEM; 153 154 if (!tdev->rx_channel) { 155 ret = snprintf(touser, 20, "<NO RX CAPABILITY>\n"); 156 ret = simple_read_from_buffer(userbuf, count, ppos, 157 touser, ret); 158 goto out; 159 } 160 161 if (tdev->rx_buffer[0] == '\0') { 162 ret = snprintf(touser, 9, "<EMPTY>\n"); 163 ret = simple_read_from_buffer(userbuf, count, ppos, 164 touser, ret); 165 goto out; 166 } 167 168 spin_lock_irqsave(&tdev->lock, flags); 169 170 ptr = tdev->rx_buffer; 171 while (l < MBOX_HEXDUMP_MAX_LEN) { 172 hex_dump_to_buffer(ptr, 173 MBOX_BYTES_PER_LINE, 174 MBOX_BYTES_PER_LINE, 1, touser + l, 175 MBOX_HEXDUMP_LINE_LEN, true); 176 177 ptr += MBOX_BYTES_PER_LINE; 178 l += MBOX_HEXDUMP_LINE_LEN; 179 *(touser + (l - 1)) = '\n'; 180 } 181 *(touser + l) = '\0'; 182 183 memset(tdev->rx_buffer, 0, MBOX_MAX_MSG_LEN); 184 185 spin_unlock_irqrestore(&tdev->lock, flags); 186 187 ret = simple_read_from_buffer(userbuf, count, ppos, touser, MBOX_HEXDUMP_MAX_LEN); 188 out: 189 kfree(touser); 190 return ret; 191 } 192 193 static const struct file_operations mbox_test_message_ops = { 194 .write = mbox_test_message_write, 195 .read = mbox_test_message_read, 196 .open = simple_open, 197 .llseek = generic_file_llseek, 198 }; 199 200 static int mbox_test_add_debugfs(struct platform_device *pdev, 201 struct mbox_test_device *tdev) 202 { 203 if (!debugfs_initialized()) 204 return 0; 205 206 root_debugfs_dir = debugfs_create_dir("mailbox", NULL); 207 if (!root_debugfs_dir) { 208 dev_err(&pdev->dev, "Failed to create Mailbox debugfs\n"); 209 return -EINVAL; 210 } 211 212 debugfs_create_file("message", 0600, root_debugfs_dir, 213 tdev, &mbox_test_message_ops); 214 215 debugfs_create_file("signal", 0200, root_debugfs_dir, 216 tdev, &mbox_test_signal_ops); 217 218 return 0; 219 } 220 221 static void mbox_test_receive_message(struct mbox_client *client, void *message) 222 { 223 struct mbox_test_device *tdev = dev_get_drvdata(client->dev); 224 unsigned long flags; 225 226 spin_lock_irqsave(&tdev->lock, flags); 227 if (tdev->rx_mmio) { 228 memcpy_fromio(tdev->rx_buffer, tdev->rx_mmio, MBOX_MAX_MSG_LEN); 229 print_hex_dump_bytes("Client: Received [MMIO]: ", DUMP_PREFIX_ADDRESS, 230 tdev->rx_buffer, MBOX_MAX_MSG_LEN); 231 } else if (message) { 232 print_hex_dump_bytes("Client: Received [API]: ", DUMP_PREFIX_ADDRESS, 233 message, MBOX_MAX_MSG_LEN); 234 memcpy(tdev->rx_buffer, message, MBOX_MAX_MSG_LEN); 235 } 236 spin_unlock_irqrestore(&tdev->lock, flags); 237 } 238 239 static void mbox_test_prepare_message(struct mbox_client *client, void *message) 240 { 241 struct mbox_test_device *tdev = dev_get_drvdata(client->dev); 242 243 if (tdev->tx_mmio) { 244 if (tdev->signal) 245 memcpy_toio(tdev->tx_mmio, tdev->message, MBOX_MAX_MSG_LEN); 246 else 247 memcpy_toio(tdev->tx_mmio, message, MBOX_MAX_MSG_LEN); 248 } 249 } 250 251 static void mbox_test_message_sent(struct mbox_client *client, 252 void *message, int r) 253 { 254 if (r) 255 dev_warn(client->dev, 256 "Client: Message could not be sent: %d\n", r); 257 else 258 dev_info(client->dev, 259 "Client: Message sent\n"); 260 } 261 262 static struct mbox_chan * 263 mbox_test_request_channel(struct platform_device *pdev, const char *name) 264 { 265 struct mbox_client *client; 266 struct mbox_chan *channel; 267 268 client = devm_kzalloc(&pdev->dev, sizeof(*client), GFP_KERNEL); 269 if (!client) 270 return ERR_PTR(-ENOMEM); 271 272 client->dev = &pdev->dev; 273 client->rx_callback = mbox_test_receive_message; 274 client->tx_prepare = mbox_test_prepare_message; 275 client->tx_done = mbox_test_message_sent; 276 client->tx_block = true; 277 client->knows_txdone = false; 278 client->tx_tout = 500; 279 280 channel = mbox_request_channel_byname(client, name); 281 if (IS_ERR(channel)) { 282 dev_warn(&pdev->dev, "Failed to request %s channel\n", name); 283 return NULL; 284 } 285 286 return channel; 287 } 288 289 static int mbox_test_probe(struct platform_device *pdev) 290 { 291 struct mbox_test_device *tdev; 292 struct resource *res; 293 int ret; 294 295 tdev = devm_kzalloc(&pdev->dev, sizeof(*tdev), GFP_KERNEL); 296 if (!tdev) 297 return -ENOMEM; 298 299 /* It's okay for MMIO to be NULL */ 300 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 301 tdev->tx_mmio = devm_ioremap_resource(&pdev->dev, res); 302 if (IS_ERR(tdev->tx_mmio)) 303 tdev->tx_mmio = NULL; 304 305 /* If specified, second reg entry is Rx MMIO */ 306 res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 307 tdev->rx_mmio = devm_ioremap_resource(&pdev->dev, res); 308 if (IS_ERR(tdev->rx_mmio)) 309 tdev->rx_mmio = tdev->tx_mmio; 310 311 tdev->tx_channel = mbox_test_request_channel(pdev, "tx"); 312 tdev->rx_channel = mbox_test_request_channel(pdev, "rx"); 313 314 if (!tdev->tx_channel && !tdev->rx_channel) 315 return -EPROBE_DEFER; 316 317 /* If Rx is not specified but has Rx MMIO, then Rx = Tx */ 318 if (!tdev->rx_channel && (tdev->rx_mmio != tdev->tx_mmio)) 319 tdev->rx_channel = tdev->tx_channel; 320 321 tdev->dev = &pdev->dev; 322 platform_set_drvdata(pdev, tdev); 323 324 spin_lock_init(&tdev->lock); 325 326 if (tdev->rx_channel) { 327 tdev->rx_buffer = devm_kzalloc(&pdev->dev, 328 MBOX_MAX_MSG_LEN, GFP_KERNEL); 329 if (!tdev->rx_buffer) 330 return -ENOMEM; 331 } 332 333 ret = mbox_test_add_debugfs(pdev, tdev); 334 if (ret) 335 return ret; 336 337 dev_info(&pdev->dev, "Successfully registered\n"); 338 339 return 0; 340 } 341 342 static int mbox_test_remove(struct platform_device *pdev) 343 { 344 struct mbox_test_device *tdev = platform_get_drvdata(pdev); 345 346 debugfs_remove_recursive(root_debugfs_dir); 347 348 if (tdev->tx_channel) 349 mbox_free_channel(tdev->tx_channel); 350 if (tdev->rx_channel) 351 mbox_free_channel(tdev->rx_channel); 352 353 return 0; 354 } 355 356 static const struct of_device_id mbox_test_match[] = { 357 { .compatible = "mailbox-test" }, 358 {}, 359 }; 360 361 static struct platform_driver mbox_test_driver = { 362 .driver = { 363 .name = "mailbox_test", 364 .of_match_table = mbox_test_match, 365 }, 366 .probe = mbox_test_probe, 367 .remove = mbox_test_remove, 368 }; 369 module_platform_driver(mbox_test_driver); 370 371 MODULE_DESCRIPTION("Generic Mailbox Testing Facility"); 372 MODULE_AUTHOR("Lee Jones <lee.jones@linaro.org"); 373 MODULE_LICENSE("GPL v2"); 374