RT-AC66 3.0.0.4.374.130 core
[tomato.git] / release / src-rt-6.x / shared / linux_gpio.c
blob2e8b4b5ecefe6db9c6dbc641588ad3fda936a0d5
1 /*
2 * Linux Broadcom BCM47xx GPIO char driver
4 * Copyright (C) 2010, Broadcom Corporation. All Rights Reserved.
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 * $Id: linux_gpio.c,v 1.10 2008-03-28 19:25:35 Exp $
20 #include <linux/module.h>
21 #include <linux/init.h>
22 #include <linux/fs.h>
23 #include <linux/miscdevice.h>
24 #include <asm/uaccess.h>
26 #include <typedefs.h>
27 #include <bcmutils.h>
28 #include <siutils.h>
29 #include <bcmdevs.h>
31 #include <linux_gpio.h>
33 /* handle to the sb */
34 static si_t *gpio_sih;
36 /* major number assigned to the device and device handles */
37 static int gpio_major;
38 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
39 static struct class *gpiodev_class = NULL;
40 #else
41 devfs_handle_t gpiodev_handle;
42 #endif
44 static int
45 gpio_open(struct inode *inode, struct file * file)
47 MOD_INC_USE_COUNT;
48 return 0;
51 static int
52 gpio_release(struct inode *inode, struct file * file)
54 MOD_DEC_USE_COUNT;
55 return 0;
58 static int
59 gpio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
61 struct gpio_ioctl gpioioc;
63 if (copy_from_user(&gpioioc, (struct gpio_ioctl *)arg, sizeof(struct gpio_ioctl)))
64 return -EFAULT;
66 switch (cmd) {
67 case GPIO_IOC_RESERVE:
68 gpioioc.val = si_gpioreserve(gpio_sih, gpioioc.mask, GPIO_APP_PRIORITY);
69 break;
70 case GPIO_IOC_RELEASE:
72 * releasing the gpio doesn't change the current
73 * value on the GPIO last write value
74 * persists till some one overwrites it
76 gpioioc.val = si_gpiorelease(gpio_sih, gpioioc.mask, GPIO_APP_PRIORITY);
77 break;
78 case GPIO_IOC_OUT:
79 gpioioc.val = si_gpioout(gpio_sih, gpioioc.mask, gpioioc.val,
80 GPIO_APP_PRIORITY);
81 break;
82 case GPIO_IOC_OUTEN:
83 gpioioc.val = si_gpioouten(gpio_sih, gpioioc.mask, gpioioc.val,
84 GPIO_APP_PRIORITY);
85 break;
86 case GPIO_IOC_IN:
87 gpioioc.val = si_gpioin(gpio_sih);
88 break;
89 default:
90 break;
92 if (copy_to_user((struct gpio_ioctl *)arg, &gpioioc, sizeof(struct gpio_ioctl)))
93 return -EFAULT;
95 return 0;
98 static struct file_operations gpio_fops = {
99 owner: THIS_MODULE,
100 open: gpio_open,
101 release: gpio_release,
102 ioctl: gpio_ioctl
105 static int __init
106 gpio_init(void)
108 if (!(gpio_sih = si_kattach(SI_OSH)))
109 return -ENODEV;
111 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
112 if ((gpio_major = register_chrdev(0, "gpio", &gpio_fops)) < 0)
113 #else
114 if ((gpio_major = devfs_register_chrdev(0, "gpio", &gpio_fops)) < 0)
115 #endif
116 return gpio_major;
117 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
118 gpiodev_class = class_create(THIS_MODULE, "gpio");
119 if (IS_ERR(gpiodev_class)) {
120 printk("Error creating gpio class\n");
121 return -1;
124 /* Add the device gpio0 */
125 class_device_create(gpiodev_class, NULL, MKDEV(gpio_major, 0), NULL, "gpio");
126 #else
127 gpiodev_handle = devfs_register(NULL, "gpio", DEVFS_FL_DEFAULT,
128 gpio_major, 0, S_IFCHR | S_IRUGO | S_IWUGO,
129 &gpio_fops, NULL);
130 #endif
132 return 0;
135 static void __exit
136 gpio_exit(void)
138 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
139 if (gpiodev_class != NULL) {
140 class_device_destroy(gpiodev_class, MKDEV(gpio_major, 0));
141 class_destroy(gpiodev_class);
144 gpiodev_class = NULL;
145 if (gpio_major >= 0)
146 unregister_chrdev(gpio_major, "gpio");
147 #else
148 if (gpiodev_handle != NULL)
149 devfs_unregister(gpiodev_handle);
150 gpiodev_handle = NULL;
151 devfs_unregister_chrdev(gpio_major, "gpio");
152 #endif
153 si_detach(gpio_sih);
156 module_init(gpio_init);
157 module_exit(gpio_exit);