Root/target/linux/brcm-2.4/files/arch/mips/bcm947xx/gpio.c

1/*
2 * GPIO char driver
3 *
4 * Copyright 2005, Broadcom Corporation
5 * All Rights Reserved.
6 *
7 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
8 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
9 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
10 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
11 *
12 */
13
14#include <linux/module.h>
15#include <linux/init.h>
16#include <linux/fs.h>
17#include <linux/miscdevice.h>
18#include <asm/uaccess.h>
19
20#include <typedefs.h>
21#include <osl.h>
22#include <sbutils.h>
23#include <bcmdevs.h>
24
25static sb_t *gpio_sbh;
26static int gpio_major;
27static devfs_handle_t gpio_dir;
28static struct {
29    char *name;
30    devfs_handle_t handle;
31} gpio_file[] = {
32    { "in", NULL },
33    { "out", NULL },
34    { "outen", NULL },
35    { "control", NULL }
36};
37
38static int
39gpio_open(struct inode *inode, struct file * file)
40{
41    if (MINOR(inode->i_rdev) > ARRAYSIZE(gpio_file))
42        return -ENODEV;
43
44    MOD_INC_USE_COUNT;
45    return 0;
46}
47
48static int
49gpio_release(struct inode *inode, struct file * file)
50{
51    MOD_DEC_USE_COUNT;
52    return 0;
53}
54
55static ssize_t
56gpio_read(struct file *file, char *buf, size_t count, loff_t *ppos)
57{
58    u32 val;
59
60    switch (MINOR(file->f_dentry->d_inode->i_rdev)) {
61    case 0:
62        val = sb_gpioin(gpio_sbh);
63        break;
64    case 1:
65        val = sb_gpioout(gpio_sbh, 0, 0, GPIO_DRV_PRIORITY);
66        break;
67    case 2:
68        val = sb_gpioouten(gpio_sbh, 0, 0, GPIO_DRV_PRIORITY);
69        break;
70    case 3:
71        val = sb_gpiocontrol(gpio_sbh, 0, 0, GPIO_DRV_PRIORITY);
72        break;
73    default:
74        return -ENODEV;
75    }
76
77    if (put_user(val, (u32 *) buf))
78        return -EFAULT;
79
80    return sizeof(val);
81}
82
83static ssize_t
84gpio_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
85{
86    u32 val;
87
88    if (get_user(val, (u32 *) buf))
89        return -EFAULT;
90
91    switch (MINOR(file->f_dentry->d_inode->i_rdev)) {
92    case 0:
93        return -EACCES;
94    case 1:
95        sb_gpioout(gpio_sbh, ~0, val, GPIO_DRV_PRIORITY);
96        break;
97    case 2:
98        sb_gpioouten(gpio_sbh, ~0, val, GPIO_DRV_PRIORITY);
99        break;
100    case 3:
101        sb_gpiocontrol(gpio_sbh, ~0, val, GPIO_DRV_PRIORITY);
102        break;
103    default:
104        return -ENODEV;
105    }
106
107    return sizeof(val);
108}
109
110static struct file_operations gpio_fops = {
111    owner: THIS_MODULE,
112    open: gpio_open,
113    release: gpio_release,
114    read: gpio_read,
115    write: gpio_write,
116};
117
118static int __init
119gpio_init(void)
120{
121    int i;
122
123    if (!(gpio_sbh = sb_kattach(SB_OSH)))
124        return -ENODEV;
125
126    sb_gpiosetcore(gpio_sbh);
127
128    if ((gpio_major = devfs_register_chrdev(0, "gpio", &gpio_fops)) < 0)
129        return gpio_major;
130
131    gpio_dir = devfs_mk_dir(NULL, "gpio", NULL);
132
133    for (i = 0; i < ARRAYSIZE(gpio_file); i++) {
134        gpio_file[i].handle = devfs_register(gpio_dir,
135                             gpio_file[i].name,
136                             DEVFS_FL_DEFAULT, gpio_major, i,
137                             S_IFCHR | S_IRUGO | S_IWUGO,
138                             &gpio_fops, NULL);
139    }
140
141    return 0;
142}
143
144static void __exit
145gpio_exit(void)
146{
147    int i;
148
149    for (i = 0; i < ARRAYSIZE(gpio_file); i++)
150        devfs_unregister(gpio_file[i].handle);
151    devfs_unregister(gpio_dir);
152    devfs_unregister_chrdev(gpio_major, "gpio");
153    sb_detach(gpio_sbh);
154}
155
156module_init(gpio_init);
157module_exit(gpio_exit);
158

Archive Download this file



interactive