1/* 2 * FILE NAME au1000_gpio.c 3 * 4 * BRIEF MODULE DESCRIPTION 5 * Driver for Alchemy Au1000 GPIO. 6 * 7 * Author: MontaVista Software, Inc. <source@mvista.com> 8 * Steve Longerbeam <stevel@mvista.com> 9 * 10 * Copyright 2001 MontaVista Software Inc. 11 * 12 * This program is free software; you can redistribute it and/or modify it 13 * under the terms of the GNU General Public License as published by the 14 * Free Software Foundation; either version 2 of the License, or (at your 15 * option) any later version. 16 * 17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 20 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 23 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 24 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * You should have received a copy of the GNU General Public License along 29 * with this program; if not, write to the Free Software Foundation, Inc., 30 * 675 Mass Ave, Cambridge, MA 02139, USA. 31 */ 32 33#include <linux/module.h> 34#include <linux/types.h> 35#include <linux/kernel.h> 36#include <linux/miscdevice.h> 37#include <linux/init.h> 38#include <asm/uaccess.h> 39#include <asm/io.h> 40#include <asm/au1000.h> 41#include <asm/au1000_gpio.h> 42 43#define VERSION "0.01" 44 45static const struct { 46 u32 active_hi; 47 u32 avail_mask; 48} pinfunc_to_avail[15] = { 49 {1, 0x7<<16}, // 0 = SSI0 / GPIO[18:16] 50 {-1, 0}, // 1 = AC97 / SSI1 51 {1, 1<<19}, // 2 = IRDA / GPIO19 52 {1, 1<<20}, // 3 = UART0 / GPIO20 53 {1, 0x1f<<24}, // 4 = NIC2 / GPIO[28:24] 54 {1, 0x7<<29}, // 5 = I2S / GPIO[31:29] 55 {0, 1<<8}, // 6 = I2SDI / GPIO8 56 {0, 0x3f<<9}, // 7 = UART3 / GPIO[14:9] 57 {0, 1<<15}, // 8 = IRFIRSEL / GPIO15 58 {0, 1<<2}, // 9 = EXTCLK0 or OSC / GPIO2 59 {0, 1<<3}, // 10 = EXTCLK1 / GPIO3 60 {0, 1<<6}, // 11 = SMROMCKE / GPIO6 61 {1, 1<<21}, // 12 = UART1 / GPIO21 62 {1, 1<<22}, // 13 = UART2 / GPIO22 63 {1, 1<<23} // 14 = UART3 / GPIO23 64}; 65 66 67u32 get_au1000_avail_gpio_mask(void) 68{ 69 int i; 70 u32 pinfunc = inl(SYS_PINFUNC); 71 u32 avail_mask = 0; // start with no gpio available 72 73 // first, check for GPIO's reprogrammed as peripheral pins 74 for (i=0; i<15; i++) { 75 if (pinfunc_to_avail[i].active_hi < 0) 76 continue; 77 if (!(pinfunc_to_avail[i].active_hi ^ 78 ((pinfunc & (1<<i)) ? 1:0))) 79 avail_mask |= pinfunc_to_avail[i].avail_mask; 80 } 81 82 // check for GPIO's used as interrupt sources 83 avail_mask &= ~(inl(IC1_MASKRD) & 84 (inl(IC1_CFG0RD) | inl(IC1_CFG1RD))); 85 86#ifdef CONFIG_USB_OHCI 87 avail_mask &= ~((1<<4) | (1<<11) | (1<<5) | (1<<13)); 88#endif 89 90 return avail_mask; 91} 92 93 94/* 95 * Tristate the requested GPIO pins specified in data. 96 * Only available GPIOs will be tristated. 97 */ 98int au1000gpio_tristate(u32 data) 99{ 100 data &= get_au1000_avail_gpio_mask(); 101 102 if (data) 103 outl(data, SYS_TRIOUTCLR); 104 105 return 0; 106} 107 108 109/* 110 * Return the pin state. Pins configured as outputs will return 111 * the output state, and pins configured as inputs (tri-stated) 112 * will return input pin state. 113 */ 114int au1000gpio_in(u32 *data) 115{ 116 *data = inl(SYS_PINSTATERD); 117 return 0; 118} 119 120 121/* 122 * Set/clear GPIO pins. Only available GPIOs will be affected. 123 */ 124int au1000gpio_set(u32 data) 125{ 126 data &= get_au1000_avail_gpio_mask(); 127 128 if (data) 129 outl(data, SYS_OUTPUTSET); 130 return 0; 131} 132 133int au1000gpio_clear(u32 data) 134{ 135 data &= get_au1000_avail_gpio_mask(); 136 137 if (data) 138 outl(data, SYS_OUTPUTCLR); 139 return 0; 140} 141 142/* 143 * Output data to GPIO pins. Only available GPIOs will be affected. 144 */ 145int au1000gpio_out(u32 data) 146{ 147 au1000gpio_set(data); 148 au1000gpio_clear(~data); 149 return 0; 150} 151 152 153EXPORT_SYMBOL(get_au1000_avail_gpio_mask); 154EXPORT_SYMBOL(au1000gpio_tristate); 155EXPORT_SYMBOL(au1000gpio_in); 156EXPORT_SYMBOL(au1000gpio_set); 157EXPORT_SYMBOL(au1000gpio_clear); 158EXPORT_SYMBOL(au1000gpio_out); 159 160 161static int au1000gpio_open(struct inode *inode, struct file *file) 162{ 163 return 0; 164} 165 166 167static int au1000gpio_release(struct inode *inode, struct file *file) 168{ 169 return 0; 170} 171 172 173static int au1000gpio_ioctl(struct inode *inode, struct file *file, 174 unsigned int cmd, unsigned long arg) 175{ 176 int status; 177 u32 val; 178 179 switch(cmd) { 180 case AU1000GPIO_IN: 181 182 status = au1000gpio_in(&val); 183 if (status != 0) 184 return status; 185 186 return put_user(val, (u32 *)arg); 187 188 case AU1000GPIO_OUT: 189 190 if (get_user(val, (u32 *)arg)) 191 return -EFAULT; 192 193 return au1000gpio_out(val); 194 195 case AU1000GPIO_SET: 196 197 if (get_user(val, (u32 *)arg)) 198 return -EFAULT; 199 200 return au1000gpio_set(val); 201 202 case AU1000GPIO_CLEAR: 203 204 if (get_user(val, (u32 *)arg)) 205 return -EFAULT; 206 207 return au1000gpio_clear(val); 208 209 case AU1000GPIO_TRISTATE: 210 211 if (get_user(val, (u32 *)arg)) 212 return -EFAULT; 213 214 return au1000gpio_tristate(val); 215 216 case AU1000GPIO_AVAIL_MASK: 217 218 return put_user(get_au1000_avail_gpio_mask(), 219 (u32 *)arg); 220 221 default: 222 return -ENOIOCTLCMD; 223 224 } 225 226 return 0; 227} 228 229 230static struct file_operations au1000gpio_fops = 231{ 232 .owner = THIS_MODULE, 233 .ioctl = au1000gpio_ioctl, 234 .open = au1000gpio_open, 235 .release = au1000gpio_release, 236}; 237 238 239static struct miscdevice au1000gpio_miscdev = 240{ 241 MISC_DYNAMIC_MINOR, 242 "au1000_gpio", 243 &au1000gpio_fops 244}; 245 246 247int __init au1000gpio_init(void) 248{ 249 misc_register(&au1000gpio_miscdev); 250 printk("Au1000 gpio driver, version %s\n", VERSION); 251 return 0; 252} 253 254 255void __exit au1000gpio_exit(void) 256{ 257 misc_deregister(&au1000gpio_miscdev); 258} 259 260 261module_init(au1000gpio_init); 262module_exit(au1000gpio_exit); 263