• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/arch/mips/brcm-boards/bcm947xx/
1/*
2 * GPIO char driver
3 *
4 * Copyright (C) 2011, 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 *
18 * $Id: gpio.c,v 1.5 2008-04-03 03:49:45 $
19 */
20
21#include <linux/module.h>
22#include <linux/init.h>
23#include <linux/fs.h>
24#include <linux/miscdevice.h>
25#include <asm/uaccess.h>
26
27#include <typedefs.h>
28#include <bcmutils.h>
29#include <siutils.h>
30#include <bcmdevs.h>
31
32static si_t *gpio_sih;
33static int gpio_major;
34static devfs_handle_t gpio_dir;
35static struct {
36	char *name;
37	devfs_handle_t handle;
38} gpio_file[] = {
39	{ "in", NULL },
40	{ "out", NULL },
41	{ "outen", NULL },
42	{ "control", NULL }
43};
44
45static int
46gpio_open(struct inode *inode, struct file * file)
47{
48	if (MINOR(inode->i_rdev) > ARRAYSIZE(gpio_file))
49		return -ENODEV;
50
51	MOD_INC_USE_COUNT;
52	return 0;
53}
54
55static int
56gpio_release(struct inode *inode, struct file * file)
57{
58	MOD_DEC_USE_COUNT;
59	return 0;
60}
61
62static ssize_t
63gpio_read(struct file *file, char *buf, size_t count, loff_t *ppos)
64{
65	u32 val;
66
67	switch (MINOR(file->f_dentry->d_inode->i_rdev)) {
68	case 0:
69		val = si_gpioin(gpio_sih);
70		break;
71	case 1:
72		val = si_gpioout(gpio_sih, 0, 0);
73		break;
74	case 2:
75		val = si_gpioouten(gpio_sih, 0, 0);
76		break;
77	case 3:
78		val = si_gpiocontrol(gpio_sih, 0, 0);
79		break;
80	default:
81		return -ENODEV;
82	}
83
84	if (put_user(val, (u32 *) buf))
85		return -EFAULT;
86
87	return sizeof(val);
88}
89
90static ssize_t
91gpio_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
92{
93	u32 val;
94
95	if (get_user(val, (u32 *) buf))
96		return -EFAULT;
97
98	switch (MINOR(file->f_dentry->d_inode->i_rdev)) {
99	case 0:
100		return -EACCES;
101	case 1:
102		si_gpioout(gpio_sih, ~0, val);
103		break;
104	case 2:
105		si_gpioouten(gpio_sih, ~0, val);
106		break;
107	case 3:
108		si_gpiocontrol(gpio_sih, ~0, val);
109		break;
110	default:
111		return -ENODEV;
112	}
113
114	return sizeof(val);
115}
116
117static struct file_operations gpio_fops = {
118	owner:		THIS_MODULE,
119	open:		gpio_open,
120	release:	gpio_release,
121	read:		gpio_read,
122	write:		gpio_write,
123};
124
125static int __init
126gpio_init(void)
127{
128	int i;
129
130	if (!(gpio_sih = si_kattach(SI_OSH)))
131		return -ENODEV;
132
133	si_gpiosetcore(gpio_sih);
134
135	if ((gpio_major = devfs_register_chrdev(0, "gpio", &gpio_fops)) < 0)
136		return gpio_major;
137
138	gpio_dir = devfs_mk_dir(NULL, "gpio", NULL);
139
140	for (i = 0; i < ARRAYSIZE(gpio_file); i++) {
141		gpio_file[i].handle = devfs_register(gpio_dir,
142						     gpio_file[i].name,
143						     DEVFS_FL_DEFAULT, gpio_major, i,
144						     S_IFCHR | S_IRUGO | S_IWUGO,
145						     &gpio_fops, NULL);
146	}
147
148	return 0;
149}
150
151static void __exit
152gpio_exit(void)
153{
154	int i;
155
156	for (i = 0; i < ARRAYSIZE(gpio_file); i++)
157		devfs_unregister(gpio_file[i].handle);
158	devfs_unregister(gpio_dir);
159	devfs_unregister_chrdev(gpio_major, "gpio");
160	si_detach(gpio_sih);
161}
162
163module_init(gpio_init);
164module_exit(gpio_exit);
165