亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? pxa2xx_i2c_misc.c

?? 基于linux xcale平臺linux系統下I2c驅動程序
?? C
字號:
/*
	created by hzh, a simple i2c driver, don't support slave and multi-master mode
 */
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/poll.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/sched.h>
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/string.h>
#include <linux/pm.h>
#include <linux/miscdevice.h>
#include <linux/device.h>
#include <linux/interrupt.h>

//#include <asm/semaphore.h>
#include <asm/hardware.h>
#include <asm/arch/pxa-regs.h>

#define I2C_MINOR		18

#define I2C_SLAVE		0x0703	/* Change slave address			*/
#define	I2C_BUS_MODE	0x0780

struct i2c_inf {
	wait_queue_head_t	int_wait;
	volatile int		bus_error;
	volatile int		tx_done;
	volatile int		rx_done;
	int					saddr;
	int					use_count;
	spinlock_t			lock;
} pxa2xx_i2c;

static __inline int _i2c_wr(struct i2c_inf *i2c, char *buf, int count, int stop)
{
	int i, flag;
	unsigned long save_flags;
//	DECLARE_WAITQUEUE(wait, current);
//	unsigned long timeout;

	for(i=0; i<count; i++) {
		i2c->bus_error = 0;
		i2c->tx_done   = 0;
		i2c->rx_done   = 0;
		ISR = 0x7f0;	//clear interrupt source
		flag = ICR & ~(ICR_MA | ICR_START | ICR_STOP | ICR_ACKNAK);
		if(i==0)
			flag |= ICR_START;
		if((i+1)==count&&stop)
			flag |= ICR_STOP;
		IDBR = buf[i];
		ICR = ICR_BEIE | ICR_ITEIE | ICR_TB | flag;
		save_and_cli(save_flags);
		if(i2c->tx_done==0) {
			interruptible_sleep_on_timeout(&i2c->int_wait, 2);
		/*	add_wait_queue(&i2c->int_wait, &wait);
			set_current_state(TASK_INTERRUPTIBLE);
			if(signal_pending(current))
				set_current_state(TASK_RUNNING);
			else
				timeout = schedule_timeout(2);
			remove_wait_queue(&i2c->int_wait, &wait);*/
		}
		restore_flags(save_flags);
		ICR &= ~(ICR_BEIE | ICR_ITEIE | ICR_START | ICR_STOP | ICR_ACKNAK);
		if(!i2c->tx_done||signal_pending(current)) {
			ICR |= ICR_MA;
			break;
		}
	}
//printk("wr %d bytes\n", i);
	return i;
}

static __inline int _i2c_rd(struct i2c_inf *i2c, char *buf, int count)
{
	int i, flag;
	unsigned long save_flags;

	for(i=0; i<count; i++) {
		i2c->bus_error = 0;
		i2c->tx_done   = 0;
		i2c->rx_done   = 0;
		ISR = 0x7f0;	//clear interrupt source
		flag = ICR & ~(ICR_MA | ICR_START | ICR_STOP | ICR_ACKNAK);
		if((i+1)==count)
			flag |= ICR_STOP | ICR_ACKNAK;
		ICR = ICR_BEIE | ICR_IRFIE | ICR_TB | flag;
		save_and_cli(save_flags);
		if(i2c->rx_done==0) {
			interruptible_sleep_on_timeout(&i2c->int_wait, 2);
		}
		restore_flags(save_flags);
		ICR &= ~(ICR_BEIE | ICR_IRFIE | ICR_START | ICR_STOP | ICR_ACKNAK);
		if(!i2c->rx_done||signal_pending(current)) {
			ICR |= ICR_MA;
			break;
		}
		buf[i] = IDBR;
	}

	return i;
}

static ssize_t pxa2xx_i2c_write(struct file *filp, const char *buf, size_t count, loff_t *l)
{
	char data[256];	//max 255
	struct i2c_inf *i2c = (struct i2c_inf *)filp->private_data;

	if(count>sizeof(data))
		return -EINVAL;
	if(!count)
		return 0;
	if(copy_from_user(data+1, buf, count))
			return -EFAULT;
	
	data[0] = i2c->saddr<<1;
	if(_i2c_wr(i2c, data, count+1, 1)==count+1)
		return count;
	return -ENXIO;
}

static ssize_t pxa2xx_i2c_read(struct file *filp, char *buf, size_t count, loff_t *l)
{
	u8 data[256];	//max 255
	struct i2c_inf *i2c = (struct i2c_inf *)filp->private_data;

	if(count>sizeof(data))
		return -EINVAL;
	if(!count)
		return 0;

	data[0] = (i2c->saddr<<1) | 1;
	if(_i2c_wr(i2c, data, 1, 0)!=1)
		return -ENXIO;
	if(_i2c_rd(i2c, data+1, count)!=count)
		return -ENXIO;
	if(copy_to_user(buf, data+1, count))
		return -EFAULT;

	return count;
}

static int pxa2xx_i2c_ioctl(struct inode * inode, struct file * filp,
				unsigned int cmd, unsigned long arg)
{
	struct i2c_inf *i2c = (struct i2c_inf *)filp->private_data;

	switch(cmd) {
	case I2C_SLAVE:
		i2c->saddr = arg;
		break;
	case I2C_BUS_MODE:
		if(arg)
			ICR |= 1<<15;
		else
			ICR &= ~(1<<15);
		break;
	default:
		return -EINVAL;
	}

	return 0;
}

static int pxa2xx_i2c_open(struct inode * inode, struct file * filp)
{
	struct i2c_inf *i2c;
	int minor = MINOR(inode->i_rdev);

	if (minor != I2C_MINOR)
		return -ENODEV;

	spin_lock_irq(&pxa2xx_i2c.lock);
	if(pxa2xx_i2c.use_count) {
		spin_unlock_irq(&pxa2xx_i2c.lock);
		return -EBUSY;
	}
	pxa2xx_i2c.use_count++;
	CKEN |= CKEN14_I2C;
	spin_unlock_irq(&pxa2xx_i2c.lock);

	filp->private_data = i2c = &pxa2xx_i2c;

	ICR = ICR_UR;
	schedule_timeout(HZ/50);
	ICR = ICR_IUE|ICR_SCLE;

	i2c->bus_error = i2c->tx_done = i2c->rx_done = 0;

	return 0;
}

static int pxa2xx_i2c_release(struct inode * inode, struct file * filp)
{
	struct i2c_inf *i2c = (struct i2c_inf *)filp->private_data;

	if (MINOR(inode->i_rdev) != I2C_MINOR)
		return -ENXIO;

	spin_lock_irq(&i2c->lock);
	i2c->use_count--;
	if(!i2c->use_count)
		CKEN &= ~CKEN14_I2C;
	spin_unlock_irq(&pxa2xx_i2c.lock);

	return 0;
}

static struct file_operations i2c_fops = {
	owner:		THIS_MODULE,
	write:		pxa2xx_i2c_write,
	read:		pxa2xx_i2c_read,
//	poll:		pxa2xx_i2c_poll,
	ioctl:		pxa2xx_i2c_ioctl,
	open:		pxa2xx_i2c_open,
	release:	pxa2xx_i2c_release,
};

static struct miscdevice i2c_misc = { 
	minor:	I2C_MINOR,
	name:	"i2c",
	fops:	&i2c_fops,
};

static irqreturn_t pxa2xx_i2c_irq(int irq, void *dev_id, struct pt_regs *regs)
{
	int status, wake=0;
	struct i2c_inf *i2c = dev_id;

	status = ISR;
//printk("S:%x,M:%x\n", status, ICR);
	if(status&ISR_BED) {
		ISR |= ISR_BED;
		i2c->bus_error = 1;
		wake = 1;
	}
	if(status&ISR_ITE) {
		ISR |= ISR_ITE;
		i2c->tx_done = 1;
		wake = 1;
	}
	if(status&ISR_IRF) {
		ISR |= ISR_IRF;
		i2c->rx_done = 1;
		wake = 1;
	}

	if(wake)
		wake_up(&i2c->int_wait);		
	else
		printk("unexpected irq, isr %x, icr %x\n", status, ICR);
	
	return IRQ_HANDLED;
}

static int pxa2xx_i2c_probe(struct device *dev)
{
	printk(KERN_INFO "PXA2XX IIC Controller Simple Driver.\n");
	
	/* register our misc device */
	if (misc_register(&i2c_misc) < 0) {
		printk(KERN_ERR "can't register misc device");
		return -EBUSY;
	}

	init_waitqueue_head(&pxa2xx_i2c.int_wait);
	spin_lock_init(&pxa2xx_i2c.lock);
	pxa_gpio_mode(GPIO117_I2CSCL_MD);
	pxa_gpio_mode(GPIO118_I2CSDA_MD);
	if(request_irq(IRQ_I2C, pxa2xx_i2c_irq, SA_INTERRUPT, "PXA-I2C", &pxa2xx_i2c)) {
		printk("fail to request irq for i2c device!\n");
		misc_deregister(&i2c_misc);
		return -EBUSY;
	}

	return 0;
}

static int  pxa2xx_i2c_remove(struct device *dev)
{
	misc_deregister(&i2c_misc);
	free_irq(IRQ_I2C, &pxa2xx_i2c);

	return 0;
}

/*
 * Suspend & Resume the IIC Controller.
 */
static int pxa2xx_i2c_suspend(struct device * dev,  u32 state, u32 level)
{
   switch(level){
   case SUSPEND_POWER_DOWN:
	break;
   }
   
   return 0;
}

static int pxa2xx_i2c_resume(struct device * dev, u32 level)
{
   switch(level){
   case RESUME_POWER_ON:
	break;
   } 

   return 0;
}

static struct device_driver pxa2xx_i2c_driver = {
	.name		=	"pxa2xx-i2c",
	.probe		=	pxa2xx_i2c_probe,
	.remove		=   pxa2xx_i2c_remove,	
	.bus		=	&platform_bus_type,	
	.suspend 	=	pxa2xx_i2c_suspend,
	.resume 	=   pxa2xx_i2c_resume,
};

static struct platform_device *pxa2xx_i2c_device = NULL;

static int __devinit pxa2xx_i2c_init(void)
{
	pxa2xx_i2c_device = platform_device_register_simple("pxa2xx-i2c", -1, NULL, 0);
	return driver_register(&pxa2xx_i2c_driver);
}

static void __exit pxa2xx_i2c_exit(void)
{
	driver_unregister(&pxa2xx_i2c_driver);
	platform_device_unregister(pxa2xx_i2c_device);
}


module_init(pxa2xx_i2c_init);
module_exit(pxa2xx_i2c_exit);

MODULE_AUTHOR("antiscle <hzh12@tom.com>");
MODULE_DESCRIPTION("pxa2xx iic simple driver");
MODULE_LICENSE("GPL");

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
91亚洲午夜精品久久久久久| 亚洲高清免费一级二级三级| 欧美色视频在线观看| 国产精品传媒视频| 99re在线视频这里只有精品| 亚洲男人的天堂网| 欧洲中文字幕精品| 蜜桃视频第一区免费观看| 欧美大白屁股肥臀xxxxxx| 精品一区二区av| 国产精品久久久一区麻豆最新章节| 99久久婷婷国产综合精品电影| 亚洲色图视频网| 6080亚洲精品一区二区| 韩国精品在线观看| 国产精品成人午夜| 精品1区2区3区| 国产一区不卡视频| 综合久久久久久| 正在播放一区二区| 国产精品一区二区久久不卡| 亚洲欧美偷拍卡通变态| 3d动漫精品啪啪一区二区竹菊| 精品一区二区在线免费观看| 成人欧美一区二区三区1314| 欧美日韩精品三区| 成人午夜在线播放| 亚洲电影在线免费观看| 国产亚洲短视频| 欧美三区在线视频| 国产精品一区2区| 亚洲国产视频一区| 国产精品污污网站在线观看| 欧美色综合影院| 国产成人午夜99999| 亚洲国产日韩av| 国产精品丝袜久久久久久app| 欧美日韩一级大片网址| 亚洲影视资源网| 久久精品夜夜夜夜久久| 3atv一区二区三区| 91在线一区二区三区| 精彩视频一区二区| 日韩av中文在线观看| 国产精品久久久久久久久动漫| 91精品在线一区二区| 91丨九色丨国产丨porny| 蜜桃视频第一区免费观看| 一区二区三区四区不卡在线| 国产日韩欧美麻豆| 欧美本精品男人aⅴ天堂| 在线观看精品一区| 国产99精品视频| 免费在线看成人av| 亚洲国产欧美在线人成| 亚洲精品久久久蜜桃| 国产蜜臀av在线一区二区三区| 欧美一级xxx| 91极品美女在线| 99精品视频一区二区三区| 国产精品小仙女| 久久精品国产77777蜜臀| 亚洲r级在线视频| 亚洲黄色小说网站| 亚洲天堂网中文字| 国产精品网站在线| 国产蜜臀97一区二区三区| 337p日本欧洲亚洲大胆精品| 欧美一激情一区二区三区| 91精品国产综合久久精品性色| 在线区一区二视频| 91精彩视频在线观看| 日本高清无吗v一区| 一本一道波多野结衣一区二区| 成人免费高清在线| 春色校园综合激情亚洲| 成人在线综合网站| 成人污视频在线观看| 成人黄动漫网站免费app| 成人av在线网| 91麻豆自制传媒国产之光| 色偷偷一区二区三区| 色国产精品一区在线观看| 色婷婷一区二区三区四区| 91激情五月电影| 777亚洲妇女| 精品国产亚洲一区二区三区在线观看| 欧美一级在线免费| 久久综合色一综合色88| 久久在线免费观看| 国产欧美日韩视频在线观看| 国产精品网曝门| 一区二区在线观看视频在线观看| 亚洲一区欧美一区| 日日夜夜精品免费视频| 理论片日本一区| 国产成人精品综合在线观看| 99在线精品视频| 欧美三级中文字幕在线观看| 欧美精品久久一区二区三区| 91精品国产综合久久精品麻豆| 亚洲精品一区二区三区四区高清| 国产性色一区二区| 亚洲裸体xxx| 日本一区中文字幕| 欧美日韩一级片网站| 欧美人妖巨大在线| 精品免费99久久| 国产精品久久久久久久久搜平片| 亚洲综合成人在线| 久久99精品视频| 不卡电影一区二区三区| 欧美色欧美亚洲另类二区| 精品美女被调教视频大全网站| 国产精品久久久久桃色tv| 亚洲国产人成综合网站| 国产精品一区二区在线观看不卡| 一本色道久久综合亚洲精品按摩| 日韩久久久精品| 国产精品久久综合| 秋霞午夜鲁丝一区二区老狼| 高清不卡一区二区在线| 欧美日韩高清影院| 国产欧美综合在线观看第十页| 亚洲小少妇裸体bbw| 国产九九视频一区二区三区| 欧美在线短视频| 国产女主播视频一区二区| 亚洲成人精品在线观看| 国产老妇另类xxxxx| 欧美日韩亚洲综合在线| 国产精品久久久久婷婷二区次| 日本91福利区| 91黄色免费观看| 久久久精品tv| 图片区日韩欧美亚洲| 大陆成人av片| 精品久久久久久久久久久久久久久| 亚洲视频网在线直播| 精品无人码麻豆乱码1区2区| 欧美日韩精品一区二区| 国产精品白丝在线| 国产一区二区三区在线观看免费 | 六月丁香综合在线视频| 91蜜桃网址入口| 欧美韩国日本不卡| 精品中文av资源站在线观看| 精品视频在线免费| 亚洲女同ⅹxx女同tv| 国产91精品一区二区麻豆网站 | 岛国一区二区三区| 欧美成人一级视频| 日韩av高清在线观看| 欧美影院一区二区| 亚洲精品乱码久久久久久黑人| jlzzjlzz亚洲女人18| 国产欧美日产一区| 国产麻豆视频一区二区| 日韩久久免费av| 另类小说综合欧美亚洲| 欧美一区二区大片| 美女久久久精品| 日韩欧美电影一二三| 九色综合国产一区二区三区| 欧美高清dvd| 视频一区欧美精品| 69成人精品免费视频| 日韩成人一区二区三区在线观看| 在线视频国内自拍亚洲视频| 亚洲一区二区三区四区在线免费观看| 91美女蜜桃在线| 亚洲精品v日韩精品| 在线观看日韩电影| 日韩电影在线一区二区三区| 91精品国模一区二区三区| 久久不见久久见免费视频7| 久久新电视剧免费观看| 国产成人av一区| 亚洲日本在线看| 欧美午夜精品电影| 日本 国产 欧美色综合| 2020国产精品自拍| av男人天堂一区| 亚洲一区中文日韩| 91精品国产欧美一区二区| 蜜桃传媒麻豆第一区在线观看| 久久久精品国产免费观看同学| 成+人+亚洲+综合天堂| 一区二区三区自拍| 欧美精品高清视频| 久久er99热精品一区二区| 国产精品免费久久| 91丝袜国产在线播放| 日本vs亚洲vs韩国一区三区| 久久综合视频网| 欧美专区日韩专区| 精品在线一区二区| **网站欧美大片在线观看| 欧美日韩精品一区二区| 国产精品一区二区视频|