leds: gpio: Support the "panic-indicator" firmware property
[linux-2.6-block.git] / drivers / mailbox / mailbox-test.c
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");