URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [char/] [au1000_gpio.c] - Rev 1275
Go to most recent revision | Compare with Previous | Blame | View Log
/* * FILE NAME au1000_gpio.c * * BRIEF MODULE DESCRIPTION * Driver for Alchemy Au1000 GPIO. * * Author: MontaVista Software, Inc. <source@mvista.com> * Steve Longerbeam <stevel@mvista.com> * * Copyright 2001 MontaVista Software Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <linux/module.h> #include <linux/config.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/miscdevice.h> #include <linux/init.h> #include <asm/uaccess.h> #include <asm/io.h> #include <asm/au1000.h> #include <asm/au1000_gpio.h> #define VERSION "0.01" static const struct { u32 active_hi; u32 avail_mask; } pinfunc_to_avail[15] = { {1, 0x7<<16}, // 0 = SSI0 / GPIO[18:16] {-1, 0}, // 1 = AC97 / SSI1 {1, 1<<19}, // 2 = IRDA / GPIO19 {1, 1<<20}, // 3 = UART0 / GPIO20 {1, 0x1f<<24}, // 4 = NIC2 / GPIO[28:24] {1, 0x7<<29}, // 5 = I2S / GPIO[31:29] {0, 1<<8}, // 6 = I2SDI / GPIO8 {0, 0x3f<<9}, // 7 = UART3 / GPIO[14:9] {0, 1<<15}, // 8 = IRFIRSEL / GPIO15 {0, 1<<2}, // 9 = EXTCLK0 or OSC / GPIO2 {0, 1<<3}, // 10 = EXTCLK1 / GPIO3 {0, 1<<6}, // 11 = SMROMCKE / GPIO6 {1, 1<<21}, // 12 = UART1 / GPIO21 {1, 1<<22}, // 13 = UART2 / GPIO22 {1, 1<<23} // 14 = UART3 / GPIO23 }; u32 get_au1000_avail_gpio_mask(void) { int i; u32 pinfunc = inl(SYS_PINFUNC); u32 avail_mask = 0; // start with no gpio available // first, check for GPIO's reprogrammed as peripheral pins for (i=0; i<15; i++) { if (pinfunc_to_avail[i].active_hi < 0) continue; if (!(pinfunc_to_avail[i].active_hi ^ ((pinfunc & (1<<i)) ? 1:0))) avail_mask |= pinfunc_to_avail[i].avail_mask; } // check for GPIO's used as interrupt sources avail_mask &= ~(inl(IC1_MASKRD) & (inl(IC1_CFG0RD) | inl(IC1_CFG1RD))); #ifdef CONFIG_USB_OHCI avail_mask &= ~((1<<4) | (1<<11)); #ifndef CONFIG_AU1X00_USB_DEVICE avail_mask &= ~((1<<5) | (1<<13)); #endif #endif return avail_mask; } /* * Tristate the requested GPIO pins specified in data. * Only available GPIOs will be tristated. */ int au1000gpio_tristate(u32 data) { data &= get_au1000_avail_gpio_mask(); if (data) outl(data, SYS_TRIOUTCLR); return 0; } /* * Return the pin state. Pins configured as outputs will return * the output state, and pins configured as inputs (tri-stated) * will return input pin state. */ int au1000gpio_in(u32 *data) { *data = inl(SYS_PINSTATERD); return 0; } /* * Set/clear GPIO pins. Only available GPIOs will be affected. */ int au1000gpio_set(u32 data) { data &= get_au1000_avail_gpio_mask(); if (data) outl(data, SYS_OUTPUTSET); return 0; } int au1000gpio_clear(u32 data) { data &= get_au1000_avail_gpio_mask(); if (data) outl(data, SYS_OUTPUTCLR); return 0; } /* * Output data to GPIO pins. Only available GPIOs will be affected. */ int au1000gpio_out(u32 data) { au1000gpio_set(data); au1000gpio_clear(~data); return 0; } EXPORT_SYMBOL(get_au1000_avail_gpio_mask); EXPORT_SYMBOL(au1000gpio_tristate); EXPORT_SYMBOL(au1000gpio_in); EXPORT_SYMBOL(au1000gpio_set); EXPORT_SYMBOL(au1000gpio_clear); EXPORT_SYMBOL(au1000gpio_out); static int au1000gpio_open(struct inode *inode, struct file *file) { MOD_INC_USE_COUNT; return 0; } static int au1000gpio_release(struct inode *inode, struct file *file) { MOD_DEC_USE_COUNT; return 0; } static int au1000gpio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int status; u32 val; switch(cmd) { case AU1000GPIO_IN: status = au1000gpio_in(&val); if (status != 0) return status; return put_user(val, (u32 *)arg); case AU1000GPIO_OUT: if (get_user(val, (u32 *)arg)) return -EFAULT; return au1000gpio_out(val); case AU1000GPIO_SET: if (get_user(val, (u32 *)arg)) return -EFAULT; return au1000gpio_set(val); case AU1000GPIO_CLEAR: if (get_user(val, (u32 *)arg)) return -EFAULT; return au1000gpio_clear(val); case AU1000GPIO_TRISTATE: if (get_user(val, (u32 *)arg)) return -EFAULT; return au1000gpio_tristate(val); case AU1000GPIO_AVAIL_MASK: return put_user(get_au1000_avail_gpio_mask(), (u32 *)arg); default: return -ENOIOCTLCMD; } return 0; } static struct file_operations au1000gpio_fops = { owner: THIS_MODULE, ioctl: au1000gpio_ioctl, open: au1000gpio_open, release: au1000gpio_release, }; static struct miscdevice au1000gpio_miscdev = { GPIO_MINOR, "au1000_gpio", &au1000gpio_fops }; int __init au1000gpio_init(void) { misc_register(&au1000gpio_miscdev); printk("Au1000 gpio driver, version %s\n", VERSION); return 0; } void __exit au1000gpio_exit(void) { misc_deregister(&au1000gpio_miscdev); } module_init(au1000gpio_init); module_exit(au1000gpio_exit);
Go to most recent revision | Compare with Previous | Blame | View Log