2 * Copyright (C) 2012 Spreadtrum Communications Inc.
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.
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.
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>
21 #include <linux/of_device.h>
24 #include <linux/sipc.h>
25 #include <linux/spipe.h>
28 struct spipe_init_data *init;
40 static struct class *spipe_class;
42 static int spipe_open(struct inode *inode, struct file *filp)
44 int minor = iminor(filp->f_path.dentry->d_inode);
45 struct spipe_device *spipe;
46 struct spipe_sbuf *sbuf;
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;
55 sbuf = kmalloc(sizeof(struct spipe_sbuf), GFP_KERNEL);
59 filp->private_data = sbuf;
61 sbuf->dst = spipe->init->dst;
62 sbuf->channel = spipe->init->channel;
63 sbuf->bufid = minor - spipe->minor;
68 static int spipe_release(struct inode *inode, struct file *filp)
70 struct spipe_sbuf *sbuf = filp->private_data;
79 static ssize_t spipe_read(struct file *filp,
80 char __user *buf, size_t count, loff_t *ppos)
82 struct spipe_sbuf *sbuf = filp->private_data;
85 if (filp->f_flags & O_NONBLOCK) {
89 return sbuf_read(sbuf->dst, sbuf->channel, sbuf->bufid,
90 (void *)buf, count, timeout);
93 static ssize_t spipe_write(struct file *filp,
94 const char __user *buf, size_t count, loff_t *ppos)
96 struct spipe_sbuf *sbuf = filp->private_data;
99 if (filp->f_flags & O_NONBLOCK) {
103 return sbuf_write(sbuf->dst, sbuf->channel, sbuf->bufid,
104 (void *)buf, count, timeout);
107 static unsigned int spipe_poll(struct file *filp, poll_table *wait)
109 struct spipe_sbuf *sbuf = filp->private_data;
111 return sbuf_poll_wait(sbuf->dst, sbuf->channel, sbuf->bufid,
115 static long spipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
120 static const struct file_operations spipe_fops = {
122 .release = spipe_release,
124 .write = spipe_write,
126 .unlocked_ioctl = spipe_ioctl,
127 .owner = THIS_MODULE,
128 .llseek = default_llseek,
131 static int spipe_parse_dt(struct spipe_init_data **init, struct device *dev)
134 struct device_node *np = dev->of_node;
135 struct spipe_init_data *pdata = NULL;
139 pdata = kzalloc(sizeof(struct spipe_init_data), GFP_KERNEL);
141 printk(KERN_ERR "Failed to allocate pdata memory\n");
145 ret = of_property_read_string(np, "sprd,name", (const char**)&pdata->name);
150 ret = of_property_read_u32(np, "sprd,dst", (uint32_t *)&data);
154 pdata->dst = (uint8_t)data;
156 ret = of_property_read_u32(np, "sprd,channel", (uint32_t *)&data);
160 pdata->channel = (uint8_t)data;
162 ret = of_property_read_u32(np, "sprd,ringnr", (uint32_t *)&pdata->ringnr);
167 ret = of_property_read_u32(np, "sprd,size-rxbuf", (uint32_t *)&pdata->rxbuf_size);
172 ret = of_property_read_u32(np, "sprd,size-txbuf", (uint32_t *)&pdata->txbuf_size);
187 static inline void spipe_destroy_pdata(struct spipe_init_data **init)
190 struct spipe_init_data *pdata = *init;
202 static int spipe_probe(struct platform_device *pdev)
204 struct spipe_init_data *init = pdev->dev.platform_data;
205 struct spipe_device *spipe;
209 if (pdev->dev.of_node && !init) {
210 rval = spipe_parse_dt(&init, &pdev->dev);
212 printk(KERN_ERR "Failed to parse spipe device tree, ret=%d\n", rval);
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);
220 rval = sbuf_create(init->dst, init->channel, init->ringnr,
221 init->txbuf_size, init->rxbuf_size);
223 printk(KERN_ERR "Failed to create sbuf: %d\n", rval);
224 spipe_destroy_pdata(&init);
228 spipe = kzalloc(sizeof(struct spipe_device), GFP_KERNEL);
230 sbuf_destroy(init->dst, init->channel);
231 spipe_destroy_pdata(&init);
232 printk(KERN_ERR "Failed to allocate spipe_device\n");
236 rval = alloc_chrdev_region(&devid, 0, init->ringnr, init->name);
238 sbuf_destroy(init->dst, init->channel);
240 spipe_destroy_pdata(&init);
241 printk(KERN_ERR "Failed to alloc spipe chrdev\n");
245 cdev_init(&(spipe->cdev), &spipe_fops);
246 rval = cdev_add(&(spipe->cdev), devid, init->ringnr);
248 sbuf_destroy(init->dst, init->channel);
250 unregister_chrdev_region(devid, init->ringnr);
251 spipe_destroy_pdata(&init);
252 printk(KERN_ERR "Failed to add spipe cdev\n");
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);
265 device_create(spipe_class, NULL,
266 MKDEV(spipe->major, spipe->minor),
267 NULL, "%s", init->name);
272 platform_set_drvdata(pdev, spipe);
277 static int spipe_remove(struct platform_device *pdev)
279 struct spipe_device *spipe = platform_get_drvdata(pdev);
282 for (i = 0; i < spipe->init->ringnr; i++) {
283 device_destroy(spipe_class,
284 MKDEV(spipe->major, spipe->minor + i));
286 cdev_del(&(spipe->cdev));
287 unregister_chrdev_region(
288 MKDEV(spipe->major, spipe->minor), spipe->init->ringnr);
290 sbuf_destroy(spipe->init->dst, spipe->init->channel);
292 spipe_destroy_pdata(&spipe->init);
296 platform_set_drvdata(pdev, NULL);
301 static const struct of_device_id spipe_match_table[] = {
302 {.compatible = "sprd,spipe", },
306 static struct platform_driver spipe_driver = {
308 .owner = THIS_MODULE,
310 .of_match_table = spipe_match_table,
312 .probe = spipe_probe,
313 .remove = spipe_remove,
316 static int __init spipe_init(void)
318 spipe_class = class_create(THIS_MODULE, "spipe");
319 if (IS_ERR(spipe_class))
320 return PTR_ERR(spipe_class);
322 return platform_driver_register(&spipe_driver);
325 static void __exit spipe_exit(void)
327 class_destroy(spipe_class);
328 platform_driver_unregister(&spipe_driver);
331 module_init(spipe_init);
332 module_exit(spipe_exit);
334 MODULE_AUTHOR("Chen Gaopeng");
335 MODULE_DESCRIPTION("SIPC/SPIPE driver");
336 MODULE_LICENSE("GPL");