⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gpio.c

📁 microwindows移植到S3C44B0的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
			return *R_PORT_G_DATA;		}		break;	case IO_SETBITS:		save_flags(flags); cli();		// set changeable bits with a 1 in arg		if (USE_PORTS(priv)) {			*priv->port = *priv->shadow |= 			  ((unsigned char)arg & priv->changeable_bits);		} else if (priv->minor == GPIO_MINOR_G) {			*R_PORT_G_DATA = port_g_data_shadow |= (arg & dir_g_out_bits);		}		restore_flags(flags);		break;	case IO_CLRBITS:		save_flags(flags); cli();		// clear changeable bits with a 1 in arg		if (USE_PORTS(priv)) {			*priv->port = *priv->shadow &= 			 ~((unsigned char)arg & priv->changeable_bits);		} else if (priv->minor == GPIO_MINOR_G) {			*R_PORT_G_DATA = port_g_data_shadow &= ~((unsigned long)arg & dir_g_out_bits);		}		restore_flags(flags);		break;	case IO_HIGHALARM:		// set alarm when bits with 1 in arg go high		priv->highalarm |= arg;		break;	case IO_LOWALARM:		// set alarm when bits with 1 in arg go low		priv->lowalarm |= arg;		break;	case IO_CLRALARM:		// clear alarm for bits with 1 in arg		priv->highalarm &= ~arg;		priv->lowalarm  &= ~arg;		break;	case IO_READDIR:		/* Read direction 0=input 1=output */		if (USE_PORTS(priv)) {			return *priv->dir_shadow;		} else if (priv->minor == GPIO_MINOR_G) {			/* Note: Some bits are both in and out,			 * Those that are dual is set hare as well.			 */			return dir_g_shadow | dir_g_out_bits;		}	case IO_SETINPUT:		/* Set direction 0=unchanged 1=input, 		 * return mask with 1=input 		 */		if (USE_PORTS(priv)) {			save_flags(flags); cli();			*priv->dir = *priv->dir_shadow &= 			~((unsigned char)arg & priv->changeable_dir);			restore_flags(flags);			return ~(*priv->dir_shadow);		} else if (priv->minor == GPIO_MINOR_G) {			/* We must fiddle with R_GEN_CONFIG to change dir */			if (((arg & dir_g_in_bits) != arg) && 			    (arg & changeable_dir_g)) {				arg &= changeable_dir_g;				/* Clear bits in genconfig to set to input */				if (arg & (1<<0)) {					genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g0dir);					dir_g_in_bits |= (1<<0);					dir_g_out_bits &= ~(1<<0);				}				if ((arg & 0x0000FF00) == 0x0000FF00) {					genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g8_15dir);					dir_g_in_bits |= 0x0000FF00;					dir_g_out_bits &= ~0x0000FF00;				}				if ((arg & 0x00FF0000) == 0x00FF0000) {					genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g16_23dir);					dir_g_in_bits |= 0x00FF0000;					dir_g_out_bits &= ~0x00FF0000;				}				if (arg & (1<<24)) {					genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG,g24dir);					dir_g_in_bits |= (1<<24);					dir_g_out_bits &= ~(1<<24);				}				printk("gpio: SETINPUT on port G set "					"genconfig to 0x%08lX "					"in_bits: 0x%08lX "					"out_bits: 0x%08lX\n", 				       (unsigned long)genconfig_shadow, 				       dir_g_in_bits, dir_g_out_bits);				*R_GEN_CONFIG = genconfig_shadow;				/* Must be a >120 ns delay before writing this again */							}			return dir_g_in_bits;		}		return 0;	case IO_SETOUTPUT:		/* Set direction 0=unchanged 1=output, 		 * return mask with 1=output 		 */		if (USE_PORTS(priv)) {			save_flags(flags); cli();			*priv->dir = *priv->dir_shadow |= 			  ((unsigned char)arg & priv->changeable_dir);			restore_flags(flags);			return *priv->dir_shadow;		} else if (priv->minor == GPIO_MINOR_G) {			/* We must fiddle with R_GEN_CONFIG to change dir */						if (((arg & dir_g_out_bits) != arg) &&			    (arg & changeable_dir_g)) {				/* Set bits in genconfig to set to output */				if (arg & (1<<0)) {					genconfig_shadow |= IO_MASK(R_GEN_CONFIG,g0dir);					dir_g_out_bits |= (1<<0);					dir_g_in_bits &= ~(1<<0);				}				if ((arg & 0x0000FF00) == 0x0000FF00) {					genconfig_shadow |= IO_MASK(R_GEN_CONFIG,g8_15dir);					dir_g_out_bits |= 0x0000FF00;					dir_g_in_bits &= ~0x0000FF00;				}				if ((arg & 0x00FF0000) == 0x00FF0000) {					genconfig_shadow |= IO_MASK(R_GEN_CONFIG,g16_23dir);					dir_g_out_bits |= 0x00FF0000;					dir_g_in_bits &= ~0x00FF0000;				}				if (arg & (1<<24)) {					genconfig_shadow |= IO_MASK(R_GEN_CONFIG,g24dir);					dir_g_out_bits |= (1<<24);					dir_g_in_bits &= ~(1<<24);				}				printk("gpio: SETOUTPUT on port G set "					"genconfig to 0x%08lX "					"in_bits: 0x%08lX "					"out_bits: 0x%08lX\n", 				       (unsigned long)genconfig_shadow, 				       dir_g_in_bits, dir_g_out_bits);				*R_GEN_CONFIG = genconfig_shadow;				/* Must be a >120 ns delay before writing this again */			}			return dir_g_out_bits;		}		return 0;	case IO_SHUTDOWN:		SOFT_SHUTDOWN();		break;	case IO_GET_PWR_BT:#if defined (CONFIG_ETRAX_SOFT_SHUTDOWN)		return (*R_PORT_G_DATA & ( 1 << CONFIG_ETRAX_POWERBUTTON_BIT));#else		return 0;#endif		break;	case IO_CFG_WRITE_MODE:		priv->clk_mask = arg & 0xFF;		priv->data_mask = (arg >> 8) & 0xFF;		priv->write_msb = (arg >> 16) & 0x01;		/* Check if we're allowed to change the bits and		 * the direction is correct		 */		if (!((priv->clk_mask & priv->changeable_bits) &&		      (priv->data_mask & priv->changeable_bits) &&		      (priv->clk_mask & *priv->dir_shadow) &&		      (priv->data_mask & *priv->dir_shadow)))		{			priv->clk_mask = 0;			priv->data_mask = 0;			return -EPERM;		}		break;	default:		if (priv->minor == GPIO_MINOR_LEDS)			return gpio_leds_ioctl(cmd, arg);		else			return -EINVAL;	} /* switch */		return 0;}static intgpio_leds_ioctl(unsigned int cmd, unsigned long arg){	unsigned char green;	unsigned char red;	switch (_IOC_NR(cmd)) {	case IO_LEDACTIVE_SET:		green = ((unsigned char) arg) & 1;		red   = (((unsigned char) arg) >> 1) & 1;		LED_ACTIVE_SET_G(green);		LED_ACTIVE_SET_R(red);		break;	case IO_LED_SETBIT:		LED_BIT_SET(arg);		break;	case IO_LED_CLRBIT:		LED_BIT_CLR(arg);		break;	default:		return -EINVAL;	} /* switch */	return 0;}struct file_operations gpio_fops = {	owner:       THIS_MODULE,	poll:        gpio_poll,	ioctl:       gpio_ioctl,	write:       gpio_write,	open:        gpio_open,	release:     gpio_release,};static void __init gpio_init_port_g(void){#define GROUPA (0x0000FF3F)#define GROUPB (1<<6 | 1<<7)#define GROUPC (1<<30 | 1<<31)#define GROUPD (0x3FFF0000)#define GROUPD_LOW (0x00FF0000)	unsigned long used_in_bits = 0;	unsigned long used_out_bits = 0;	if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, scsi0, select)){		used_in_bits  |= GROUPA | GROUPB | 0 | 0;		used_out_bits |= GROUPA | GROUPB | 0 | 0;	}	if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, ata, select)) {		used_in_bits  |= GROUPA | GROUPB | GROUPC | (GROUPD & ~(1<<25|1<<26));		used_out_bits |= GROUPA | GROUPB | GROUPC | GROUPD;	}	if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, par0, select)) {		used_in_bits  |= (GROUPA & ~(1<<0)) | 0 | 0 | 0;		used_out_bits |= (GROUPA & ~(1<<0)) | 0 | 0 | 0;	}	if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, ser2, select)) {		used_in_bits  |= 0 | GROUPB | 0 | 0;		used_out_bits |= 0 | GROUPB | 0 | 0;	}	/* mio same as shared RAM ? */	if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, mio, select)) {		used_in_bits  |= (GROUPA & ~(1<<0)) | 0 |0 |GROUPD_LOW;		used_out_bits |= (GROUPA & ~(1<<0|1<<1|1<<2)) | 0 |0 |GROUPD_LOW;	}	if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, scsi1, select)) {		used_in_bits  |= 0 | 0 | GROUPC | GROUPD;		used_out_bits |= 0 | 0 | GROUPC | GROUPD;	}	if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, scsi0w, select)) {		used_in_bits  |= GROUPA | GROUPB | 0 | (GROUPD_LOW | 1<<24);		used_out_bits |= GROUPA | GROUPB | 0 | (GROUPD_LOW | 1<<24 | 1<<25|1<<26);	}	if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, par1, select)) {		used_in_bits  |= 0 | 0 | 0 | (GROUPD & ~(1<<24));		used_out_bits |= 0 | 0 | 0 | (GROUPD & ~(1<<24));	}	if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, ser3, select)) {		used_in_bits  |= 0 | 0 | GROUPC | 0;		used_out_bits |= 0 | 0 | GROUPC | 0;	}	/* mio same as shared RAM-W? */	if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, mio_w, select)) {		used_in_bits  |= (GROUPA & ~(1<<0)) | 0 | 0 |GROUPD_LOW;		used_out_bits |= (GROUPA & ~(1<<0|1<<1|1<<2)) | 0 | 0 |GROUPD_LOW;	}	/* TODO: USB p2, parw, sync ser3? */	/* Initialise the dir_g_shadow etc. depending on genconfig */	/* 0=input 1=output */	if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g0dir, out)) 		dir_g_shadow |= (1 << 0);	if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g8_15dir, out))		dir_g_shadow |= 0x0000FF00;	if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g16_23dir, out))		dir_g_shadow |= 0x00FF0000;	if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g24dir, out))		dir_g_shadow |= (1 << 24);	dir_g_in_bits = ~used_in_bits;	dir_g_out_bits = ~used_out_bits;	changeable_dir_g = 0x01FFFF01; /* all that can change dir */	changeable_dir_g &= dir_g_out_bits;	changeable_dir_g &= dir_g_in_bits;	/* Correct the bits that can change direction */ 	dir_g_out_bits &= ~changeable_dir_g;	dir_g_out_bits |= dir_g_shadow;	dir_g_in_bits &= ~changeable_dir_g;	dir_g_in_bits |= (~dir_g_shadow & changeable_dir_g);	printk("GPIO port G: in_bits: 0x%08lX out_bits: 0x%08lX val: %08lX\n",	       dir_g_in_bits, dir_g_out_bits, (unsigned long)*R_PORT_G_DATA);	printk("GPIO port G: dir: %08lX changeable: %08lX\n", 	       dir_g_shadow, changeable_dir_g);}/* main driver initialization routine, called from mem.c */static __init intgpio_init(void){	extern void init_ioremap(void);	int res;#if defined (CONFIG_ETRAX_CSP0_LEDS)	int i;#endif	/* do the formalities */	res = register_chrdev(GPIO_MAJOR, gpio_name, &gpio_fops);	if (res < 0) {		printk(KERN_ERR "gpio: couldn't get a major number.\n");		return res;	}	/* Clear all leds */#if defined (CONFIG_ETRAX_CSP0_LEDS) ||  defined (CONFIG_ETRAX_PA_LEDS) || defined (CONFIG_ETRAX_PB_LEDS) 	init_ioremap();	LED_NETWORK_SET(0);	LED_ACTIVE_SET(0);	LED_DISK_READ(0);	LED_DISK_WRITE(0);#if defined (CONFIG_ETRAX_CSP0_LEDS)	for (i = 0; i < 32; i++) {		LED_BIT_SET(i);	}#endif#endif	gpio_init_port_g();	printk("ETRAX 100LX GPIO driver v2.3, (c) 2001, 2002 Axis Communications AB\n");	return res;}/* this makes sure that gpio_init is called during kernel boot */module_init(gpio_init);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -