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