Input: sprd_eic_keys: remove event log
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / drivers / sipc / spipe.c
1 /*
2  * Copyright (C) 2012 Spreadtrum Communications Inc.
3  *
4  * This software is licensed under the terms of the GNU General Public
5  * License version 2, as published by the Free Software Foundation, and
6  * may be copied, distributed, and modified under those terms.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  */
13
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/cdev.h>
17 #include <linux/poll.h>
18 #include <linux/platform_device.h>
19 #include <linux/slab.h>
20 #ifdef CONFIG_OF
21 #include <linux/of_device.h>
22 #endif
23
24 #include <linux/sipc.h>
25 #include <linux/spipe.h>
26
27 struct spipe_device {
28         struct spipe_init_data  *init;
29         int                     major;
30         int                     minor;
31         struct cdev             cdev;
32 };
33
34 struct spipe_sbuf {
35         uint8_t                 dst;
36         uint8_t                 channel;
37         uint32_t                bufid;
38 };
39
40 static struct class             *spipe_class;
41
42 static int spipe_open(struct inode *inode, struct file *filp)
43 {
44         int minor = iminor(filp->f_path.dentry->d_inode);
45         struct spipe_device *spipe;
46         struct spipe_sbuf *sbuf;
47
48         spipe = container_of(inode->i_cdev, struct spipe_device, cdev);
49         if (sbuf_status(spipe->init->dst, spipe->init->channel) != 0) {
50                 printk(KERN_ERR "spipe %d-%d not ready to open!\n", spipe->init->dst, spipe->init->channel);
51                 filp->private_data = NULL;
52                 return -ENODEV;
53         }
54
55         sbuf = kmalloc(sizeof(struct spipe_sbuf), GFP_KERNEL);
56         if (!sbuf) {
57                 return -ENOMEM;
58         }
59         filp->private_data = sbuf;
60
61         sbuf->dst = spipe->init->dst;
62         sbuf->channel = spipe->init->channel;
63         sbuf->bufid = minor - spipe->minor;
64
65         return 0;
66 }
67
68 static int spipe_release(struct inode *inode, struct file *filp)
69 {
70         struct spipe_sbuf *sbuf = filp->private_data;
71
72         if (sbuf) {
73                 kfree(sbuf);
74         }
75
76         return 0;
77 }
78
79 static ssize_t spipe_read(struct file *filp,
80                 char __user *buf, size_t count, loff_t *ppos)
81 {
82         struct spipe_sbuf *sbuf = filp->private_data;
83         int timeout = -1;
84
85         if (filp->f_flags & O_NONBLOCK) {
86                 timeout = 0;
87         }
88
89         return sbuf_read(sbuf->dst, sbuf->channel, sbuf->bufid,
90                         (void *)buf, count, timeout);
91 }
92
93 static ssize_t spipe_write(struct file *filp,
94                 const char __user *buf, size_t count, loff_t *ppos)
95 {
96         struct spipe_sbuf *sbuf = filp->private_data;
97         int timeout = -1;
98
99         if (filp->f_flags & O_NONBLOCK) {
100                 timeout = 0;
101         }
102
103         return sbuf_write(sbuf->dst, sbuf->channel, sbuf->bufid,
104                         (void *)buf, count, timeout);
105 }
106
107 static unsigned int spipe_poll(struct file *filp, poll_table *wait)
108 {
109         struct spipe_sbuf *sbuf = filp->private_data;
110
111         return sbuf_poll_wait(sbuf->dst, sbuf->channel, sbuf->bufid,
112                         filp, wait);
113 }
114
115 static long spipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
116 {
117         return 0;
118 }
119
120 static const struct file_operations spipe_fops = {
121         .open           = spipe_open,
122         .release        = spipe_release,
123         .read           = spipe_read,
124         .write          = spipe_write,
125         .poll           = spipe_poll,
126         .unlocked_ioctl = spipe_ioctl,
127         .owner          = THIS_MODULE,
128         .llseek         = default_llseek,
129 };
130
131 static int spipe_parse_dt(struct spipe_init_data **init, struct device *dev)
132 {
133 #ifdef CONFIG_OF
134         struct device_node *np = dev->of_node;
135         struct spipe_init_data *pdata = NULL;
136         int ret;
137         uint32_t data;
138
139         pdata = kzalloc(sizeof(struct spipe_init_data), GFP_KERNEL);
140         if (!pdata) {
141                 printk(KERN_ERR "Failed to allocate pdata memory\n");
142                 return -ENOMEM;
143         }
144
145         ret = of_property_read_string(np, "sprd,name", (const char**)&pdata->name);
146         if (ret) {
147                 goto error;
148         }
149
150         ret = of_property_read_u32(np, "sprd,dst", (uint32_t *)&data);
151         if (ret) {
152                 goto error;
153         }
154         pdata->dst = (uint8_t)data;
155
156         ret = of_property_read_u32(np, "sprd,channel", (uint32_t *)&data);
157         if (ret) {
158                 goto error;
159         }
160         pdata->channel = (uint8_t)data;
161
162         ret = of_property_read_u32(np, "sprd,ringnr", (uint32_t *)&pdata->ringnr);
163         if (ret) {
164                 goto error;
165         }
166
167         ret = of_property_read_u32(np, "sprd,size-rxbuf", (uint32_t *)&pdata->rxbuf_size);
168         if (ret) {
169                 goto error;
170         }
171
172         ret = of_property_read_u32(np, "sprd,size-txbuf", (uint32_t *)&pdata->txbuf_size);
173         if (ret) {
174                 goto error;
175         }
176         *init = pdata;
177         return ret;
178 error:
179         kfree(pdata);
180         *init = NULL;
181         return ret;
182 #else
183         return -ENODEV;
184 #endif
185 }
186
187 static inline void spipe_destroy_pdata(struct spipe_init_data **init)
188 {
189 #ifdef CONFIG_OF
190         struct spipe_init_data *pdata = *init;
191
192         if (pdata) {
193                 kfree(pdata);
194         }
195
196         *init = NULL;
197 #else
198         return;
199 #endif
200 }
201
202 static int spipe_probe(struct platform_device *pdev)
203 {
204         struct spipe_init_data *init = pdev->dev.platform_data;
205         struct spipe_device *spipe;
206         dev_t devid;
207         int i, rval;
208
209         if (pdev->dev.of_node && !init) {
210                 rval = spipe_parse_dt(&init, &pdev->dev);
211                 if (rval) {
212                         printk(KERN_ERR "Failed to parse spipe device tree, ret=%d\n", rval);
213                         return rval;
214                 }
215         }
216         pr_info("spipe: after parse device tree, name=%s, dst=%u, channel=%u, ringnr=%u, rxbuf_size=%u, txbuf_size=%u\n",
217                 init->name, init->dst, init->channel, init->ringnr, init->rxbuf_size, init->txbuf_size);
218
219
220         rval = sbuf_create(init->dst, init->channel, init->ringnr,
221                 init->txbuf_size, init->rxbuf_size);
222         if (rval != 0) {
223                 printk(KERN_ERR "Failed to create sbuf: %d\n", rval);
224                 spipe_destroy_pdata(&init);
225                 return rval;
226         }
227
228         spipe = kzalloc(sizeof(struct spipe_device), GFP_KERNEL);
229         if (spipe == NULL) {
230                 sbuf_destroy(init->dst, init->channel);
231                 spipe_destroy_pdata(&init);
232                 printk(KERN_ERR "Failed to allocate spipe_device\n");
233                 return -ENOMEM;
234         }
235
236         rval = alloc_chrdev_region(&devid, 0, init->ringnr, init->name);
237         if (rval != 0) {
238                 sbuf_destroy(init->dst, init->channel);
239                 kfree(spipe);
240                 spipe_destroy_pdata(&init);
241                 printk(KERN_ERR "Failed to alloc spipe chrdev\n");
242                 return rval;
243         }
244
245         cdev_init(&(spipe->cdev), &spipe_fops);
246         rval = cdev_add(&(spipe->cdev), devid, init->ringnr);
247         if (rval != 0) {
248                 sbuf_destroy(init->dst, init->channel);
249                 kfree(spipe);
250                 unregister_chrdev_region(devid, init->ringnr);
251                 spipe_destroy_pdata(&init);
252                 printk(KERN_ERR "Failed to add spipe cdev\n");
253                 return rval;
254         }
255
256         spipe->major = MAJOR(devid);
257         spipe->minor = MINOR(devid);
258         if (init->ringnr > 1) {
259                 for (i = 0; i < init->ringnr; i++) {
260                         device_create(spipe_class, NULL,
261                                 MKDEV(spipe->major, spipe->minor + i),
262                                 NULL, "%s%d", init->name, i);
263                 }
264         } else {
265                 device_create(spipe_class, NULL,
266                         MKDEV(spipe->major, spipe->minor),
267                         NULL, "%s", init->name);
268         }
269
270         spipe->init = init;
271
272         platform_set_drvdata(pdev, spipe);
273
274         return 0;
275 }
276
277 static int  spipe_remove(struct platform_device *pdev)
278 {
279         struct spipe_device *spipe = platform_get_drvdata(pdev);
280         int i;
281
282         for (i = 0; i < spipe->init->ringnr; i++) {
283                 device_destroy(spipe_class,
284                                 MKDEV(spipe->major, spipe->minor + i));
285         }
286         cdev_del(&(spipe->cdev));
287         unregister_chrdev_region(
288                 MKDEV(spipe->major, spipe->minor), spipe->init->ringnr);
289
290         sbuf_destroy(spipe->init->dst, spipe->init->channel);
291
292         spipe_destroy_pdata(&spipe->init);
293
294         kfree(spipe);
295
296         platform_set_drvdata(pdev, NULL);
297
298         return 0;
299 }
300
301 static const struct of_device_id spipe_match_table[] = {
302         {.compatible = "sprd,spipe", },
303         { },
304 };
305
306 static struct platform_driver spipe_driver = {
307         .driver = {
308                 .owner = THIS_MODULE,
309                 .name = "spipe",
310                 .of_match_table = spipe_match_table,
311         },
312         .probe = spipe_probe,
313         .remove = spipe_remove,
314 };
315
316 static int __init spipe_init(void)
317 {
318         spipe_class = class_create(THIS_MODULE, "spipe");
319         if (IS_ERR(spipe_class))
320                 return PTR_ERR(spipe_class);
321
322         return platform_driver_register(&spipe_driver);
323 }
324
325 static void __exit spipe_exit(void)
326 {
327         class_destroy(spipe_class);
328         platform_driver_unregister(&spipe_driver);
329 }
330
331 module_init(spipe_init);
332 module_exit(spipe_exit);
333
334 MODULE_AUTHOR("Chen Gaopeng");
335 MODULE_DESCRIPTION("SIPC/SPIPE driver");
336 MODULE_LICENSE("GPL");