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

📄 misc_gpio.c

📁 嵌入式linux系统下hi3510平台的osd开发源码
💻 C
字号:
/* 
 * extdrv/peripheral/misc_gpio/msic_gpio.c
 *
 * Copyright (c) 2006 Hisilicon Co., Ltd. 
 *
 * 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 program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; 
 *
 * History: 
 *      10-April-2006 create this file
 */
 
 
#include <linux/config.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/string.h>
#include <linux/poll.h>
#include <linux/interrupt.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/timer.h>
#include <linux/miscdevice.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/ioctl.h>

#include "hi_gpio.h"
#include "misc_gpio.h"

func_type sd_hook = NULL;

static int sd_state = 0;
unsigned int         	misc_gpio_major = 0;
static int 			     ch = 0;
static struct   timer_list usb_delay_timer;
static struct   timer_list sd_delay_timer;

/* 
 *	initalize gpio config
 */
void gpio_init(void)
{
    	unsigned int tmp;
    	gpio_dirgetbyte(GPIO_2_PORT,&tmp);
    	tmp |= 0x44;
    	tmp &= 0xfd;
    	
    	/* set gpio_2 dir: in 2、6 out 1 */
    	gpio_dirsetbyte(GPIO_2_PORT,tmp);
    	
    	/* set gpio_2 interrupt mode */
    	gpio_interruptset_byte(
                              		GPIO_2_PORT, 
                              		0x02, 
                              		SENSE_BOTH, 
                              		SENSE_LEVEL, 
                              		EVENT_FALLING_EDGE
                            	);
        
        /* disable gpio_2_1 interrupt */                    	
    	tmp = 0x02;
    	gpio_interruptdisable_byte(GPIO_2_PORT,tmp);
    	
    	/* set gpio_2_2、6 low */
    	writew(0x00,(GPIO_2_PORT_ADDR+0x110));   
    	
    	/* clear the int_flags of gpio_2_1 */ 
    	tmp = 0x02;
    	gpio_interruptclear_byte(GPIO_2_PORT,tmp);
    
    	gpio_dirgetbyte(GPIO_3_PORT,&tmp);
    	tmp |= 0x02;
    	tmp &= 0xf7;
    	
    	/* set gpio_3 dir: in 3 out 1 */
    	gpio_dirsetbyte(GPIO_3_PORT,tmp);
    	
    	/* set gpio_3 interrupt mode */
    	gpio_interruptset_byte(
                              		GPIO_3_PORT, 
                              		0x08, 
                              		SENSE_BOTH, 
                              		SENSE_EDGE, 
                              		EVENT_FALLING_EDGE
                            	);
    	/* disable gpio_3_3 interrupt */
    	tmp = 0x08;
    	gpio_interruptdisable_byte(GPIO_3_PORT,tmp);
    	
    	/* if SD card insert, open power gpio_3_1=0. else close power gpio_3_1=1*/
    	tmp=readw(GPIO_3_PORT_ADDR+0x20);
    	tmp &= 0x08; 
    	if(!tmp)
          	writew(0x02,GPIO_3_PORT_ADDR+0x08);
    	else      
          	writew(0x0,(GPIO_3_PORT_ADDR+0x08)); 
          	   	
    	/* clear the int_flags of gpio_3_3 */
    	tmp = 0x08;
    	gpio_interruptclear_byte(GPIO_3_PORT,tmp);
    	/* enable interrupt gpio_3_3 */    
    	tmp = 0x08;
    	gpio_interruptenable_byte(GPIO_3_PORT,tmp);
    	/* enable interrupt gpio_2_1 */  
    	tmp = 0x02;
    	gpio_interruptenable_byte(GPIO_2_PORT,tmp);
}


/*
 *	usb power abnormal interrupt handle and start time_list
 */
static irqreturn_t  usb_power_ctrl_inth(int irq, void *dev_id, struct pt_regs *reg)
{ 
    	unsigned int  tmp;
    	unsigned char current_irq; 
    	int handled = 0;
     
        /* disable usb power abnormal interrupt*/
    	tmp = 0x02;
    	gpio_interruptdisable_byte(GPIO_2_PORT,tmp);  
    	         
    	current_irq=readw(GPIO_2_PORT_ADDR+GPIO_RIS);
    	current_irq =current_irq & 0x02;
    	if (current_irq != 0x02)
    	{
    		printk("interrupt num of USB is wrong!\n");
    	        handled = 1;
    	        return IRQ_RETVAL(handled);
    	}
    
        /* close usb power */
    	tmp = readw(GPIO_2_PORT_ADDR + 0x10);
    	tmp ^= 0x04;
    	writew(tmp,GPIO_2_PORT_ADDR + 0x10);
    	tmp &= 0x04;    	
    	printk("close USB power!\n");      
        
        /* set the time to wait */
    	usb_delay_timer.expires = jiffies + margin_usb;
    	/* start to wait */
    	add_timer (&usb_delay_timer);           

    	handled = 1;
    	return IRQ_RETVAL(handled);
}


/*
 *	margin_usb later, open usb power
 */
static void usb_delay_timer_handler(unsigned long data)    
{
    	unsigned int tmp;
    	tmp = 0x02;     	
    	gpio_interruptclear_byte (GPIO_2_PORT,tmp);     	
    	tmp = readw(GPIO_2_PORT_ADDR + 0x10);
    	tmp ^= 0x04;
    	writew(tmp,GPIO_2_PORT_ADDR + 0x10);    
    	printk("open USB power!\n"); 
    	tmp = 0x02;    
    	gpio_interruptenable_byte(GPIO_2_PORT,tmp);
}


/*
 *	sd insert detect interrupt handle and start time_list
 */
static irqreturn_t  sd_detect_inth(int irq, void *dev_id, struct pt_regs *reg)
{ 
    	unsigned int  tmp;
    	unsigned char current_irq; 
    	int handled = 0;
    	tmp= 0x08;
    	gpio_interruptdisable_byte(GPIO_3_PORT,tmp); 
    	
    	current_irq = readw(GPIO_3_PORT_ADDR+GPIO_RIS);
    	current_irq = current_irq & 0x08;
    	if (current_irq != 0x08)
    	{
    		printk("the interrupt num of SD is wrong!\n");
    		handled = 1;
    		return IRQ_RETVAL(handled);
    	}
   /*
    	tmp = readw(GPIO_3_PORT_ADDR + 0x20);
    	tmp &= 0x08;
    	if (!tmp)
    	{
    		printk("open SD power!\n");
    		writew(0x02,GPIO_3_PORT_ADDR+0x08);
    		sd_state = 1;  
    		if (sd_hook)  
    			sd_hook(sd_state);		
    	}
    	else
    	{
    		printk("close SD power!\n");
    		writew(0x00,GPIO_3_PORT_ADDR+0x08);
    		sd_state = 0;
    		if (sd_hook)  
    			sd_hook(sd_state);	 		
    	}
    */
    	sd_delay_timer.expires = jiffies + margin_sd;
    	add_timer (&sd_delay_timer);   
 
    	handled = 1;
    	return IRQ_RETVAL(handled);
}


static void sd_delay_timer_handler(unsigned long data)    
{
    	unsigned int tmp; 
    	
    	tmp = readw(GPIO_3_PORT_ADDR + 0x20);
    	tmp &= 0x08;
    	if (!tmp)
    	{
    		printk("open SD power!\n");
    		writew(0x02,GPIO_3_PORT_ADDR+0x08);
    		sd_state = 1;  
    		if (sd_hook)  
    			sd_hook(sd_state);		
    	}
    	else
    	{
    		printk("close SD power!\n");
    		writew(0x00,GPIO_3_PORT_ADDR+0x08);
    		sd_state = 0;
    		if (sd_hook)  
    			sd_hook(sd_state);	 		
    	}   	
    	
    	tmp = 0x08;
    	gpio_interruptclear_byte(GPIO_3_PORT,tmp);     	
    	tmp = 0x08;
    	gpio_interruptenable_byte(GPIO_3_PORT,tmp);    
}

/* 
 *	open dev, init gpio
 */
static int misc_gpio_open(struct inode *inode ,struct file *file)
{
    	gpio_init();
    	return 0;
}

/*
 *	close device, do nothing
 */
static int misc_gpio_release(struct inode *inode ,struct file *file)
{
    	return 0;
}


/*
 *	ioctl method. to choose the Tw2834 or DC by arg
 */
static int twdc_choose_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{ 
    	unsigned int tmp;	
    	switch(cmd) 
    	{ 
    		case SULL_IOCMISCGPIO:
    	    		if (arg == CHOOSE_TW2834)
    	    		{
    	    			tmp = readw(GPIO_2_PORT_ADDR + 0x100);
                		tmp &= 0xbf;
                		writew(tmp,GPIO_2_PORT_ADDR + 0x100);
            		}
    	    		else if(arg == CHOOSE_DC)
    	     		{
    	    			tmp = readw(GPIO_2_PORT_ADDR + 0x100);
                		tmp |= 0x40;
                		writew(tmp,GPIO_2_PORT_ADDR + 0x100);    	    	
    	    		}	
    	    		return 0;    	      
        	default: 
            		return -EINVAL; 
    	} 
} 
  
 
static struct file_operations misc_gpio_fops =
{ 
    	owner:    THIS_MODULE, 
    	open:     misc_gpio_open,
    	release:  misc_gpio_release,
    	ioctl:    twdc_choose_ioctl,     
}; 

int get_sd_state(void)
{
	return sd_state;
}

void sd_insert_hook(func_type function_ptr)
{
	sd_hook = function_ptr;
}

static struct miscdevice misc_gpio_dev = {
	MISC_DYNAMIC_MINOR,
	"misc_gpio",
	&misc_gpio_fops,
};
   
static int __init  misc_gpio_init(void)
{ 
    	int ret; 
    	unsigned int tmp;
    	ret = misc_register(&misc_gpio_dev);
    	if (ret) 
    	{ 
        	printk(DEVICE_NAME " can't register major number\n"); 
        	return ret; 
    	}    

    	gpio_remap();
    	gpio_init();
    	init_timer(&usb_delay_timer);
    	init_timer(&sd_delay_timer);
    	usb_delay_timer.function = usb_delay_timer_handler;
    	sd_delay_timer.function = sd_delay_timer_handler;
    	
    	ret = request_irq(IRQ_2,&usb_power_ctrl_inth,0,"usb_power_int",NULL); 
    	if (ret) 
    	{   
	        del_timer(&usb_delay_timer);
	        del_timer(&sd_delay_timer);    		
          misc_deregister(&misc_gpio_dev);
        	gpio_unmap();
		      printk(DEVICE_NAME " can't request irq(%d)\n",IRQ_2);
 		      return ret;
    	}
    
    	ret = request_irq(IRQ_3,&sd_detect_inth,0,"sd_power_int",NULL); 
    	if (ret) 
    	{   
	        del_timer(&usb_delay_timer);
	        del_timer(&sd_delay_timer);    		
    		  free_irq(IRQ_2,NULL);
        	misc_deregister(&misc_gpio_dev);
        	gpio_unmap();
		      printk(DEVICE_NAME " can't request irq(%d)\n",IRQ_2);
 		      return ret;
    	} 
    	
    	tmp = readw(GPIO_3_PORT_ADDR + 0x20);
    	tmp &= 0x08;
    	if (!tmp)
    	{
    		printk("open SD power!\n");
    		writew(0x02,GPIO_3_PORT_ADDR+0x08);
    		sd_state = 1;
    	}
    	else
    	{
    		printk("close SD power!\n");
    		writew(0x00,GPIO_3_PORT_ADDR+0x08);
    		sd_state = 0;    		
    	}    	
    	
    	if (ch == 0)
    	{
    	    	tmp = readw(GPIO_2_PORT_ADDR + 0x100);
                tmp &= 0xbf;
                writew(tmp,GPIO_2_PORT_ADDR + 0x100);
         }
    	 else if(ch == 1)
    	 {
    	    	tmp = readw(GPIO_2_PORT_ADDR + 0x100);
                tmp |= 0x40;
                writew(tmp,GPIO_2_PORT_ADDR + 0x100);    	    	
    	 }	    	
    	printk("misc gpio control Driver v1.0\n");
    	return 0; 
} 


static void __exit misc_gpio_exit(void) 
{ 
	    del_timer(&usb_delay_timer);
	    del_timer(&sd_delay_timer);
    	free_irq(IRQ_2,NULL); 
    	free_irq(IRQ_3,NULL);
      misc_deregister(&misc_gpio_dev);
    	gpio_unmap();
}


module_init(misc_gpio_init);
module_exit(misc_gpio_exit);
/* input param with insmod. */
module_param(ch, int, 0);
MODULE_PARM_DESC(ch, "'0'for 2834.'1'for DC");
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(get_sd_state);
EXPORT_SYMBOL(sd_insert_hook);

⌨️ 快捷键说明

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