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/sprdmux.h>
24 struct mux_init_data *init;
35 static struct class *mux_class;
37 static int mux_open(struct inode *inode, struct file *filp)
39 int minor = iminor(filp->f_path.dentry->d_inode);
40 struct mux_device *mux;
41 struct mux_channel *channel;
42 int rval, mux_id, line;
44 mux = container_of(inode->i_cdev, struct mux_device, cdev);
47 printk(KERN_ERR "MUX: Error %s mux_dev is NULL\n", __FUNCTION__);
51 mux_id = mux->init->id;
53 rval = ts0710_mux_status(mux_id);
55 printk(KERN_ERR "MUX: Error %s [%d] mux_status is Not OK\n", __FUNCTION__, mux->init->id);
56 filp->private_data = NULL;
60 printk(KERN_ERR "MUX: %s mux_id = %d, minor = %d, mux->minor = %d\n", __FUNCTION__, mux_id , minor, mux->minor);
62 line = minor - mux->minor;
64 rval = ts0710_mux_open(mux_id, line);
66 printk(KERN_ERR "MUX: Error %s id[%d] line[%d] mux_open is Not OK\n", __FUNCTION__, mux->init->id, line);
67 filp->private_data = NULL;
71 channel = kmalloc(sizeof(struct mux_channel), GFP_KERNEL);
76 channel->mux_id = mux_id;
79 filp->private_data = channel;
84 static int mux_release(struct inode *inode, struct file *filp)
86 struct mux_channel *channel = filp->private_data;
88 if (channel == NULL) {
89 printk(KERN_ERR "MUX: Error %s channel is NULL\n", __FUNCTION__);
93 ts0710_mux_close(channel->mux_id, channel->line);
100 static ssize_t mux_read(struct file *filp,
101 char __user *buf, size_t count, loff_t *ppos)
104 struct mux_channel *channel = filp->private_data;
106 if (channel == NULL) {
107 printk(KERN_ERR "MUX: Error %s channel is NULL\n", __FUNCTION__);
111 if (filp->f_flags & O_NONBLOCK) {
115 return ts0710_mux_read(channel->mux_id, channel->line, buf, count, timeout);
119 static ssize_t mux_write(struct file *filp,
120 const char __user *buf, size_t count, loff_t *ppos)
123 struct mux_channel *channel = filp->private_data;
125 if (channel == NULL) {
126 printk(KERN_ERR "MUX: Error %s channel is NULL\n", __FUNCTION__);
130 if (filp->f_flags & O_NONBLOCK) {
134 return ts0710_mux_write(channel->mux_id, channel->line, buf, count, timeout);
138 static unsigned int mux_poll(struct file *filp, poll_table *wait)
140 struct mux_channel *channel = filp->private_data;
142 if (channel == NULL) {
143 printk(KERN_ERR "MUX: Error %s channel is NULL\n", __FUNCTION__);
147 return ts0710_mux_poll_wait(channel->mux_id, channel->line, filp, wait);
150 static long mux_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
152 struct mux_channel *channel = filp->private_data;
154 if (channel == NULL) {
155 printk(KERN_ERR "MUX: Error %s channel is NULL\n", __FUNCTION__);
159 return ts0710_mux_mux_ioctl(channel->mux_id, channel->line, cmd, arg);
162 static const struct file_operations mux_fops = {
164 .release = mux_release,
168 .unlocked_ioctl = mux_ioctl,
169 .owner = THIS_MODULE,
170 .llseek = default_llseek,
173 static int mux_probe(struct platform_device *pdev)
177 struct mux_device *mux;
178 struct mux_init_data *init = pdev->dev.platform_data;
180 mux = kzalloc(sizeof(struct mux_device), GFP_KERNEL);
182 printk(KERN_ERR "MUX: Error %s no memory for mux\n", __FUNCTION__);
186 rval = alloc_chrdev_region(&devid, 0, init->num, init->name);
189 printk(KERN_ERR "MUX: Error %s no memory for dev_region\n", __FUNCTION__);
193 cdev_init(&(mux->cdev), &mux_fops);
195 rval = cdev_add(&(mux->cdev), devid, init->num);
198 unregister_chrdev_region(devid, init->num);
199 printk(KERN_ERR "MUX: Error %s add error\n", __FUNCTION__);
203 mux->major = MAJOR(devid);
204 mux->minor = MINOR(devid);
207 for (i = 0; i < init->num; i++) {
208 device_create(mux_class, NULL,
209 MKDEV(mux->major, mux->minor + i),
210 NULL, "%s%d", init->name, i);
213 device_create(mux_class, NULL,
214 MKDEV(mux->major, mux->minor),
215 NULL, "%s", init->name);
220 platform_set_drvdata(pdev, mux);
225 static int mux_remove(struct platform_device *pdev)
228 struct mux_device *mux = platform_get_drvdata(pdev);
230 for (i = 0; i < mux->init->num; i++) {
231 device_destroy(mux_class, MKDEV(mux->major, mux->minor + i));
234 cdev_del(&(mux->cdev));
236 unregister_chrdev_region(MKDEV(mux->major, mux->minor), mux->init->num);
240 platform_set_drvdata(pdev, NULL);
245 static struct platform_driver mux_driver = {
247 .owner = THIS_MODULE,
251 .remove = mux_remove,
254 static int __init mux_init(void)
256 printk(KERN_ERR "MUX: %s entered\n", __FUNCTION__);
260 mux_class = class_create(THIS_MODULE, "mux");
261 if (IS_ERR(mux_class))
262 return PTR_ERR(mux_class);
264 return platform_driver_register(&mux_driver);
267 static void __exit mux_exit(void)
269 printk(KERN_ERR "MUX: %s entered\n", __FUNCTION__);
271 class_destroy(mux_class);
272 platform_driver_unregister(&mux_driver);
275 module_init(mux_init);
276 module_exit(mux_exit);
278 MODULE_AUTHOR("Wu Jiaoyou");
279 MODULE_DESCRIPTION("mux driver");
280 MODULE_LICENSE("GPL");