1/* 2 * Linux Broadcom BCM47xx GPIO char driver 3 * 4 * Copyright 2007, 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 * $Id: linux_gpio.c,v 1.1.1.1 2008/10/15 03:31:34 james26_jang Exp $ 12 * 13 */ 14 15#include <linux/module.h> 16#include <linux/init.h> 17#include <linux/fs.h> 18#include <linux/miscdevice.h> 19#include <asm/uaccess.h> 20 21#include <typedefs.h> 22#include <bcmutils.h> 23#include <sbutils.h> 24#include <bcmdevs.h> 25 26#include <linux_gpio.h> 27 28/* handle to the sb */ 29static sb_t *gpio_sbh; 30 31/* major number assigned to the device and device handles */ 32static int gpio_major; 33devfs_handle_t gpiodev_handle; 34 35static int 36gpio_open(struct inode *inode, struct file * file) 37{ 38 MOD_INC_USE_COUNT; 39 return 0; 40} 41 42static int 43gpio_release(struct inode *inode, struct file * file) 44{ 45 MOD_DEC_USE_COUNT; 46 return 0; 47} 48 49static int 50gpio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) 51{ 52 struct gpio_ioctl gpioioc; 53 54 if (copy_from_user(&gpioioc, (struct gpio_ioctl *)arg, sizeof(struct gpio_ioctl))) 55 return -EFAULT; 56 57 switch (cmd) { 58 case GPIO_IOC_RESERVE: 59 gpioioc.val = sb_gpioreserve(gpio_sbh, gpioioc.mask, GPIO_APP_PRIORITY); 60 break; 61 case GPIO_IOC_RELEASE: 62 /* 63 * releasing the gpio doesn't change the current 64 * value on the GPIO last write value 65 * persists till some one overwrites it 66 */ 67 gpioioc.val = sb_gpiorelease(gpio_sbh, gpioioc.mask, GPIO_APP_PRIORITY); 68 break; 69 case GPIO_IOC_OUT: 70 gpioioc.val = sb_gpioout(gpio_sbh, gpioioc.mask, gpioioc.val, 71 GPIO_APP_PRIORITY); 72 break; 73 case GPIO_IOC_OUTEN: 74 gpioioc.val = sb_gpioouten(gpio_sbh, gpioioc.mask, gpioioc.val, 75 GPIO_APP_PRIORITY); 76 break; 77 case GPIO_IOC_IN: 78 gpioioc.val = sb_gpioin(gpio_sbh); 79 break; 80 default: 81 break; 82 } 83 if (copy_to_user((struct gpio_ioctl *)arg, &gpioioc, sizeof(struct gpio_ioctl))) 84 return -EFAULT; 85 86 return 0; 87 88} 89static struct file_operations gpio_fops = { 90 owner: THIS_MODULE, 91 open: gpio_open, 92 release: gpio_release, 93 ioctl: gpio_ioctl, 94 }; 95 96static int __init 97gpio_init(void) 98{ 99 if (!(gpio_sbh = sb_kattach(SB_OSH))) 100 return -ENODEV; 101 102 if ((gpio_major = devfs_register_chrdev(0, "gpio", &gpio_fops)) < 0) 103 return gpio_major; 104 105 gpiodev_handle = devfs_register(NULL, "gpio", DEVFS_FL_DEFAULT, 106 gpio_major, 0, S_IFCHR | S_IRUGO | S_IWUGO, 107 &gpio_fops, NULL); 108 109 return 0; 110} 111 112static void __exit 113gpio_exit(void) 114{ 115 if (gpiodev_handle != NULL) 116 devfs_unregister(gpiodev_handle); 117 gpiodev_handle = NULL; 118 devfs_unregister_chrdev(gpio_major, "gpio"); 119 sb_detach(gpio_sbh); 120} 121 122module_init(gpio_init); 123module_exit(gpio_exit); 124