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

📄 csi.c

📁 linux下面csi模块的驱动程序,在填加好该驱动以后,主要要修改好makefile文件啊
💻 C
📖 第 1 页 / 共 2 页
字号:
	int korder;	int required_pages;	int extra_pages;//alloc a tmp buffer in kernel space	required_pages = byte_size >> PAGE_SHIFT;	for (korder = 0 ; required_pages >> korder ; korder++) {;}	extra_pages = (1 << korder) - required_pages;	_kbuf = (unsigned int *)__get_free_pages(GFP_KERNEL, korder);	if(!_kbuf)	{		printk("csi error: buffer alloc failed\n");		return -1;	}	//poll sof	_reg_CSI_CSISR = BIT_SOF_INT;	while(!(_reg_CSI_CSISR & BIT_SOF_INT));	_reg_CSI_CSISR = BIT_SOF_INT;//clear fifo overflow	if(_reg_CSI_CSISR & BIT_RFF_OR_INT)		_reg_CSI_CSISR = BIT_RFF_OR_INT;//read rx fifo	j = 0;	while(1)	{	//overflow check		if(_reg_CSI_CSISR & BIT_RFF_OR_INT)		{//			printk("csi error: overflow\n");			_reg_CSI_CSISR = BIT_RFF_OR_INT;		}	//poll rx fifo full		if(_reg_CSI_CSISR & BIT_RXFF_INT)		{			for(i = 0; i < g_csi_cfg.rxff_level; i ++)				_kbuf[j ++] = _reg_CSI_CSIRXR;		}		if(j >= word_size)			break;	}	copy_to_user(_buf, _kbuf, byte_size);	free_pages((int)_kbuf, korder);	_kbuf = 0;	return 0;}static void csihw_reset_frame_count(void){	_reg_CSI_CSICR3 |= BIT_FRMCNT_RST;	return;}static int csihw_get_frame_count(void){	int count;	count = _reg_CSI_CSICR3 >> SHIFT_FRMCNT;	return count;}//block until eof is detected//not to be used with prpstatic int csihw_pol_eof(int rxcnt){	int cnt = 0;	int trial_cnt = 10000000;		if(rxcnt != 0)	{		//use this rxcnt		_reg_CSI_CSIRXCNT = rxcnt;	}	else	{		//otherwise use the rxcnt in csi config		_reg_CSI_CSIRXCNT = g_csi_cfg.rxcnt;	}	//clear interrupt first	if(_reg_CSI_CSISR & BIT_EOF_INT)		_reg_CSI_CSISR = BIT_EOF_INT;		while(1)	{		if(_reg_CSI_CSISR & BIT_EOF_INT)		{			_reg_CSI_CSISR = BIT_EOF_INT;			break;		}		else		{			if(cnt ++ > trial_cnt)			{//				printk("csi err: eof timeout\n");				return 1;			}		}	}	return 0;}//block until sof is detectedstatic int csihw_pol_sof(void){	int cnt = 0;	int trial_cnt = 10000000;	//clear interrupt first	if(_reg_CSI_CSISR & BIT_SOF_INT)		_reg_CSI_CSISR = BIT_SOF_INT;		while(1)	{		if(_reg_CSI_CSISR & BIT_SOF_INT)		{			_reg_CSI_CSISR = BIT_SOF_INT;			break;		}		else		{			if(cnt ++ > trial_cnt)			{				printk("csi err: sof timeout\n");				return 1;			}		}	}	return 0;}static void csihw_clock_enable(void){//turn on hclk & perclk4//caution -- if sensor clock (mclk) is provided by csi,//           make sure csi is resumed before sensor is resumed	_reg_CRM_PCCR0 |= 0x80000000;	if(g_csi_ver == 2)		_reg_CRM_PCCR0 |= 0x00400000;		return;	}static void csihw_clock_disable(void){//shutdown hclk & perclk4//caution -- if sensor clock (mclk) is provided by csi,//           make sure the sensor is suspend before csi is suspend	_reg_CRM_PCCR0 &= ~0x80000000;	if(g_csi_ver == 2)		_reg_CRM_PCCR0 &= ~0x00400000;	return;}//csi reset, really can reset??static void csihw_reset(void){	csihw_clock_enable();		_reg_CSI_CSICR1 = CSICR1_RESET_VAL;	_reg_CSI_CSICR2 = CSICR2_RESET_VAL;	if(g_csi_ver == 2)	{		_reg_CSI_CSICR3 = CSICR3_RESET_VAL;			//need to enable hclk before CSICR3 can be access	}	return;}/********************************************************************************---------------------------- LINUX OS SPECIFIC -------------------------------*///global staticstatic devfs_handle_t devfs_handle = NULL;static int gMajor = 0;static struct pm_dev *pmdev;static struct apmc_user *g_csi_apmc;//functions and interfacestatic int csi_open(struct inode *inode, struct file *filp);static int csi_release(struct inode *inode, struct file *filp);static ssize_t csi_read(struct file *filp, char *buf, size_t size, loff_t *l);static ssize_t csi_write(struct file *filp, const char *buf, size_t size, loff_t *l);static int csi_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);static int csi_pm_handler(struct pm_dev *pmdev, pm_request_t rqst, void *data);struct file_operations csi_fops = {	open:		csi_open,	release:	csi_release,	read:		csi_read,	write:		csi_write,	ioctl:		csi_ioctl,};/***@brief	The module entry function of the CSI driver.*       It does only the basic things such as csihw_init() and register_chrdev().*       Module clock is turned on in open().*       DMA & IRQ are turned on later in the function csihw_config().**@return      @li    0     Success*                 @li     others     Failure*/int __init init_module(){	int result;	printk("Motorola CSI Linux driver ver 0.1\n"		" - Copyright (C) 2004 Motorola Inc\n\n");	csihw_init();//register CSI character device 	result = devfs_register_chrdev(0, "csi", &csi_fops); 	if ( result < 0 ) 	{		printk("csi error: unable to register chr driver\n");		return -ENODEV;	}	devfs_handle = devfs_register(NULL, "csi", DEVFS_FL_DEFAULT,				      result, 0,				      S_IFCHR | S_IRUSR | S_IWUSR,				      &csi_fops, NULL);	if(devfs_handle == NULL)	{		printk("csi error: unable to register driver\n");		return -ENODEV;	}	gMajor = result;	g_csi_busy = 0;//power management	if ((pmdev = pm_register(PM_CSI_DEV, PM_SYS_UNKNOWN, csi_pm_handler)) == NULL)	{		printk("csi error: failed to register PM... continuing with driver init\n");	}	g_csi_apmc = apmc_register(APMC_LEVEL_HIGHEST);   	return 0;}/***@brief	The module exit function of the CSI driver.**@return   NULL*/void __exit cleanup_module(){ 	csihw_cleanup();	apmc_unregister(g_csi_apmc);	pm_unregister(pmdev);   	if(gMajor > 0)   	{		if(devfs_unregister_chrdev(gMajor, "csi") < 0)		{			printk("csi error: failed to unregister from devfs\n");			return;		}	}	if(devfs_handle != NULL)		devfs_unregister(devfs_handle);	else	{		printk("csi error: failed to unregister from devfs, devfs_handle = 0x%08X\n", (int)devfs_handle);		return;	}	printk("CSI driver is unloaded sucessfully\n");		return;}/***@brief	Open the CSI **@param	 inode structure inode list pointer*@param filp structure file list pointer*@return 0*/static int csi_open(struct inode *inode, struct file *filp){	csihw_open();	        MOD_INC_USE_COUNT; 	return 0;}/***@brief	Release the CSI **@param	 inode structure inode list pointer*@param filp structure file list pointer*@return 0*/static int csi_release(struct inode *inode, struct file *filp){	csihw_release();        MOD_DEC_USE_COUNT;	return 0;	}/***@brief	This function is to read the data from the CSI client device through the CSI interface.*       Reading the data by calling the function csihw_poll().**@param filp   structure file list pointer*@param	 buf   the buffer to store the data*@param size   size of the buffer, the number of bytes*@param l   loff_t type pointer, not used*@return  0*/static ssize_t csi_read(struct file *filp, char *buf, size_t size, loff_t *l){	g_csi_busy = 1;	csihw_poll((unsigned int *)buf, (int)size);	g_csi_busy = 0;		return 0;}/***@brief	This function is only called when "csi error: write ioctl is not implemented" happens.*       csi_write() includes only a statement "printk" because it's unnecessary to write to a CSI client device.**@param filp   structure file list pointer*@param	 buf   the buffer to store the data*@param size   size of the buffer*@param l   the register number in the I2C slave (SSI sensor)*@return -1*/static ssize_t csi_write(struct file *filp, const char *buf, size_t size, loff_t *l){	printk("csi error: write ioctl is not implemented\n");	return -1;}/***@brief	CSI ioctl operation**There are five kinds of commands*@li IOCTL_CSI_READ_CONFIG*@li IOCTL_CSI_CONFIG*@li IOCTL_CSI_READ_STATUS*@li IOCTL_CSI_GET_FRMCNT*@li IOCTL_CSI_RST_FRMCNT**@param	 inode   structure inode list pointer*@param filp   structure file list pointer*@param cmd  The command to control the codec.*@param arg   The void pointer used to communicate with user space.*@return      @li 0          Success*                 @li others     Failure*/static int csi_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){	switch(cmd)	{		case IOCTL_CSI_READ_CONFIG:		{			csihw_read_config(&g_csi_cfg);			if(copy_to_user((void *)arg, (void *)&g_csi_cfg, sizeof(CSI_CFG)))				return -EFAULT;			break;		}		case IOCTL_CSI_CONFIG:		{			if(copy_from_user((void *)&g_csi_cfg, (void *)arg, sizeof(CSI_CFG)))				return -EFAULT;			csihw_config(&g_csi_cfg);			break;		}		case IOCTL_CSI_READ_STATUS:		{			csihw_read_status(&g_csi_status);			if(copy_to_user((void *)arg, (void *)&g_csi_status, sizeof(CSI_STATUS)))				return -EFAULT;						break;		}		case IOCTL_CSI_GET_FRMCNT:		{			int count;			count = csihw_get_frame_count();			if(copy_to_user((void *)arg, (void *)&count, sizeof(int)))				return -EFAULT;						break;		}		case IOCTL_CSI_RST_FRMCNT:		{			csihw_reset_frame_count();						break;		}		case IOCTL_CSI_POLL_EOF:		{			csihw_pol_eof(arg);	//block						break;		}		case IOCTL_CSI_POLL_SOF:		{			csihw_pol_sof();	//block						break;		}		case IOCTL_CSI_RESET:		{			csihw_reset();						break;		}	}		return 0;}static int csi_pm_handler(struct pm_dev *pmdev, pm_request_t rqst, void *data){	switch(rqst)	{		case PM_SUSPEND:		{			if(g_csi_busy)			{				//does not allow suspend when there is a data transfer between csi fifo & memory				return 1;			}			else			{				csihw_clock_disable();//				printk("csi: suspend\n");			}			break;		}		case PM_RESUME:		{			csihw_clock_enable();//			printk("csi: resume\n");			break;		}	}		return 0;}/**@}*/

⌨️ 快捷键说明

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