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

📄 1wire.c

📁 freescale的关于Imax21的1wire程序,好用
💻 C
字号:
/*! \brief file header
 *         the source file for 1wire driver  
 * 
 * File Name: onewire.c
 *
 * Programers: 
 *
 * Date of Creations:   20 Oct,2003
 *
 * Synopsis:
 *
 * Descirption:
 * 	Driver for the DB-MX21 OneWire 
 *
 * Modification History:
 * 
 *
 */

#include <linux/module.h>
#include <linux/version.h>

#include <linux/init.h>
#include <linux/fs.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <asm/uaccess.h>

#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/interrupt.h>
#include <linux/ptrace.h>
#include <linux/ioport.h>
#include <linux/in.h>
#include <linux/miscdevice.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/string.h>
#include <linux/init.h>
#include <asm/bitops.h>
#include <asm/io.h>
#include <linux/errno.h>
#include <linux/tqueue.h>
#include <linux/wait.h>

#include <asm/irq.h>
#include <asm/arch/hardware.h>
#include <asm/arch/irqs.h>
#include <asm/arch/mx2.h>
#include <linux/pm.h>


///register definition
#define _reg_OWIRE_CTRL0			(*((volatile u16*)(MX2_IO_ADDRESS(0x10009000))))	///  16bit owire control reg
#define _reg_OWIRE_TIME_DIV0		(*((volatile u16*)(MX2_IO_ADDRESS(0x10009002))))	///  16bit owire time divider reg
#define _reg_OWIRE_RESET0			(*((volatile u16*)(MX2_IO_ADDRESS(0x10009004))))	///  16bit owire reset reg


#define MODULE_NAME "Owire"
//#define DBMX_DEBUG 1
#ifdef DBMX_DEBUG
#define TRACE(fmt, args...) \
	{ \
		printk("\n %s:%d:%s:",__FILE__, __LINE__,__FUNCTION__); \
		printk(fmt, ## args);\
	}
#else
#define TRACE(fmt, args...)
#endif

#define FAILED(fmt, args...) \
	{ \
		printk("\n %s:%d:%s:",__FILE__, __LINE__,__FUNCTION__); \
		printk(fmt, ## args);\
	}

#define INFO(fmt, args...) \
	{ \
		printk("\n"); \
		printk(fmt, ## args);\
	}



///Private Function Declearation
static int Owire_open(struct inode * inode, 
		struct file * filp);
static int Owire_release(struct inode * inode, 
		struct file * filp);
static int Owire_fasync(int fd, 
		struct file *filp, 
		int mode);
ssize_t Owire_read(struct file * filp, 
					char * buf, 
					size_t count, 
					loff_t * l);
static ssize_t Owire_write(struct file *file, 
							const char *buffer, 
							size_t count, 
							loff_t *ppos);
static int Owire_ioctl(struct inode * inode, 
		struct file *filp,
		unsigned int cmd , 
		unsigned long arg);
static unsigned int Owire_poll(struct file * filp, 
		struct poll_table_struct * wait);



/// globale variables
struct file_operations g_Owire_fops = {
	open:           Owire_open,
	release:        Owire_release,
	write:          Owire_write,
	read:           Owire_read,
	poll:           Owire_poll,
	ioctl:          Owire_ioctl,
	fasync:         Owire_fasync,
};

static devfs_handle_t g_devfs_handle;
int g_Owire_major = 0;

struct pm_dev *g_Owire_pm;

static int g_Owire_status;
#define OWIRE_OPEN_STATUS		0x0001
#define OWIRE_SUSPEND_STATUS	0x0002

/**
 * Function Name: Owire_open
 *
 * Input: 		inode	:
 * 				filp	:
 * Value Returned:	int	: Return status.If no error, return 0.
 *
 * Description: allocate resource when open the inode
 *
 */
int Owire_open(struct inode * inode, struct file * filp)
{
	///set AIPI1_PSR0 bit[9] and clear AIPI1_PSR1bit[9] to match 1-wire bus width 16bits
	_reg_AIPI1_PSR0 |= 0x00200;
	_reg_AIPI1_PSR1 &= ~0x00200;
	
	TRACE("_reg_AIPI1_PSR0=%x, _reg_AIPI1_PSR1=%x \n",_reg_AIPI1_PSR0,_reg_AIPI1_PSR1);
	///enable clk
	_reg_CRM_PCCR1 |= 0x80000000;
	///GPIO config
	_reg_GPIO_GIUS(GPIOE) &= ~0x00010000;
	_reg_GPIO_GPR(GPIOE) |= 0x00010000;
	
   	///reset the 1-wire module
  	_reg_OWIRE_RESET0 |= 1;
  	_reg_OWIRE_RESET0 = 0;
 	
  	///set the time devider to get the 1M clk from the main clock
	_reg_OWIRE_TIME_DIV0 = 0x2B;


	_reg_OWIRE_CTRL0 |= 0x80;//control register bit 7 = 1;
	///check if PST is set
	udelay(610);
	TRACE("_reg_OWIRE_CTRL0 = %x \n",_reg_OWIRE_CTRL0);
	///check if RPP self cleared
	udelay(400);
	TRACE("_reg_OWIRE_CTRL0 = %x \n",_reg_OWIRE_CTRL0);
	g_Owire_status = OWIRE_OPEN_STATUS;

	MOD_INC_USE_COUNT;
	return 0;
}

/*!
 * Function Name: Owire_release
 *
 * Input: 		inode	:
 * 			filp	:
 * Value Returned:	int	: Return status.If no error, return 0.
 *
 * Description: release resource when close the inode
 *
 */
int Owire_release(struct inode * inode, struct file * filp)
{ 
	g_Owire_status &= ~OWIRE_OPEN_STATUS;
	//disable clk
	_reg_CRM_PCCR1 &= ~0x80000000;
	MOD_DEC_USE_COUNT;
	return 0;
}

/**
 * Function Name: Owire_read
 *
 * Input: 		filp	: the file 
 * 			buf	: data buffer
 * 			count	: number of chars to be readed
 * 			l	: offset of file
 * Value Returned:	int	: Return status.If no error, return 0.
 *
 * Description: read device driver
 *
 */
ssize_t Owire_read(struct file * filp, char * buf, size_t count, loff_t * l)
{
	int i,j;
	char tmp,value;
	char *pBuf;
	pBuf = buf;
	TRACE("count = %d \n",count);
	for(i=0;i<count;i++)
	{
		value = 0;
		for(j=0;j<8;j++)
		{
			///control register bit 4 = 1
			//_reg_OWIRE_CTRL0 &= 0xEF;
			_reg_OWIRE_CTRL0 |= 0x10;
			udelay(117);
			
			tmp = (_reg_OWIRE_CTRL0 & 0x08)? 1:0;
			value |= tmp<<j; 
		}
		TRACE("value %d = %x \n",i,value);
		__copy_to_user(pBuf,&value,1);
		pBuf++;
		
	}
	TRACE("read finished \n");
	return count;
}

/**
 * Function Name: Owire_write
 *
 * Input: 		filp	: the file
 * 			buf	: data buffer
 * 			count	: number of chars to be read
 * 			l	: offset of file
 * Value Returned:	int	: Return status.If no error, return 0.
 *
 * Description: write device driver
 *
 */
ssize_t Owire_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
{
	int 	i,j;
	char 	value,tmp;

	for(i=0;i<count;i++)
	{
		__copy_from_user(&value,buffer,1);
		TRACE("value = %x \n",value);
		for(j=0; j<8; j++)
		{
			tmp = value & 0x01;
			if(tmp == 0)
			{///control register bit 5 = 1
				_reg_OWIRE_CTRL0 |= 0x20;
				udelay(117);
			}
			else if(tmp == 1)
			{///control register bit 4 = 1
				_reg_OWIRE_CTRL0 |= 0x10;
				udelay(117);
			}
			value>>=1;
		}
		buffer++;
	}
	TRACE("write finished \n");
	return count;
}

/**
 * Function Name: Owire_fasync
 *
 * Input: 		fd	:
 * 			filp	:
 * 			mode	:
 * Value Returned:	int	: Return status.If no error, return 0.
 *
 * Description: provide fasync functionality for select system call
 *
 */
static int Owire_fasync(int fd, struct file *filp, int mode)
{	
	return 0;
}
/**
 * Function Name: check_device
 *
 * Input: 		inode	:
 * Value Returned:	int	: Return status.If no error, return 0.
 *
 * Description: verify if the inode is a correct inode
 *
 */
static int check_device(struct inode *pInode)
{
	int minor;
	kdev_t dev = pInode->i_rdev;
	
	if( MAJOR(dev) != g_Owire_major)
	{
		printk("Owire: check_device bad major = %d\n",MAJOR(dev) );
		return -1;
	}
	minor = MINOR(dev);
	
	if ( minor < 1 )
		return minor;
	else
	{       
		printk("Owire: check_device bad minor = %d\n",minor );
		return -1;
	}
}

/**
 * Function Name: Owire_ioctl
 *
 * Input: 	inode	:
 * 			filp	:
 * 			cmd	: command for ioctl
 * 			arg	: parameter for command
 * Value Returned:	int	: Return status.If no error, return 0.
 *
 * Description: ioctl for this device driver
 *
 * 	
 */
int Owire_ioctl(struct inode * inode, 
		struct file *filp,
		unsigned int cmd , 
		unsigned long arg)
{
	int ret = -EIO;
	int minor;	
	
	minor = check_device( inode );
	if ( minor == - 1)
	{
		printk("OneWire_ioctl:bad minor\n");
		return -ENODEV;
	}
	
	printk("OneWire_ioctl:minor=%08x cmd=%d\n",minor,cmd);
	
	return ret;
}

/**
 * Function Name: Owire_poll
 *
 * Input: 		filp	:
 * 			wait	: 
 * Value Returned:	int	: Return status.If no error, return 0.
 *
 * Description: support poll and select
 *
 */
unsigned int Owire_poll(struct file * filp, struct poll_table_struct * wait)
{	
	return 0;
}

int Owire_pm_handler(struct pm_dev *dev, pm_request_t rqst, void *data)
{
	switch(rqst){
		case PM_RESUME:
			if((g_Owire_status & OWIRE_SUSPEND_STATUS)!=0)
			{
				//enable clk
				_reg_CRM_PCCR1 |= 0x80000000;
				g_Owire_status &= ~OWIRE_SUSPEND_STATUS;
			}
			break;
		case PM_SUSPEND:
			if((g_Owire_status & OWIRE_OPEN_STATUS)!=0)
			{
				//disable clk
				_reg_CRM_PCCR1 &= ~0x80000000;
				g_Owire_status |= OWIRE_SUSPEND_STATUS;
			
			}
			break;
		default:
			break;
		}
	return 0;
}
/**
 * Function Name: init_module
 *
 * Input: 		void	:
 * Value Returned:	int	: Return status.If no error, return 0.
 *
 * Description: device driver initialization
 *
 */
 
#ifdef MODULE
int init_module(void)
#else
int __init Owire_init(void)
#endif
{
	/* register our character device */
    g_Owire_major = devfs_register_chrdev(0, MODULE_NAME, &g_Owire_fops);
 	if ( g_Owire_major < 0 )
 	{
		TRACE("%s driver: Unable to register driver\n",MODULE_NAME);
		return -ENODEV;
	}

	g_devfs_handle = devfs_register(NULL, MODULE_NAME, DEVFS_FL_DEFAULT,
				      g_Owire_major, 0,
				      S_IFCHR | S_IRUSR | S_IWUSR,
				      &g_Owire_fops, NULL);   	

	g_Owire_pm = pm_register(PM_SYS_DEV,PM_SYS_VGA,Owire_pm_handler);
	g_Owire_status = 0;
	INFO("Owire Driver 0.1.0\n");
	INFO("Motorols SPS-Suzhou\n");

	return 0;
}


/******************************************************************************
 * Function Name: Owire_cleanup
 *
 * Input: 		void	:
 * Value Returned:	void	: 
 *
 * Description: clean up and free all of resource for this MODULE
 *
 * Modification History:
 * 	
 *****************************************************************************/
#ifdef MODULE
void cleanup_module(void)
#else
void __exit Owire_cleanup(void)
#endif
{
	devfs_unregister_chrdev(g_Owire_major, MODULE_NAME);
    devfs_unregister(g_devfs_handle);
    pm_unregister(g_Owire_pm);
}

#ifndef MODULE
module_init(Owire_init);
module_exit(Owire_cleanup);
#endif
/* end of file */

⌨️ 快捷键说明

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