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

📄 i2c-keywest.c

📁 s3c2410上面的I2C驱动程序,直接insmod就可以用了
💻 C
📖 第 1 页 / 共 2 页
字号:
	/* State machine, to turn into an interrupt handler */	while(iface->state != state_idle) {		u8 isr = wait_interrupt(iface);		handle_interrupt(iface, isr);	}#else /* POLLED_MODE */	DBG("using interrupt mode...\n");	wait_for_completion(&iface->complete);	#endif /* POLLED_MODE */		rc = iface->result;		DBG("transfer done, result: %d\n", rc);	if (rc == 0 && size == I2C_SMBUS_WORD_DATA && read_write == I2C_SMBUS_READ)	    	data->word = le16_to_cpu(cur_word);		/* Release sem */	up(&iface->sem);		return rc;}/* * Generic i2c master transfer entrypoint */static intkeywest_xfer(	struct i2c_adapter *adap,		struct i2c_msg msgs[], 		int num){	struct keywest_chan* chan = (struct keywest_chan*)adap->data;	struct keywest_iface* iface = chan->iface;	struct i2c_msg *pmsg;	int i, completed;	int rc = 0;	down(&iface->sem);	/* Set adapter to standard mode */	iface->cur_mode &= ~KW_I2C_MODE_MODE_MASK;	iface->cur_mode |= KW_I2C_MODE_STANDARD;	completed = 0;	for (i = 0; rc >= 0 && i < num;) {		u8 addr;				pmsg = &msgs[i++];		addr = pmsg->addr;		if (pmsg->flags & I2C_M_TEN) {			printk(KERN_ERR "i2c-keywest: 10 bits addr not supported !\n");			rc = -EINVAL;			break;		}		DBG("xfer: chan: %d, doing %s %d bytes to 0x%02x - %d of %d messages\n",		     chan->chan_no,		     pmsg->flags & I2C_M_RD ? "read" : "write",                     pmsg->len, addr, i, num);    		/* Setup channel & clear pending irqs */		write_reg(reg_mode, iface->cur_mode | (chan->chan_no << 4));		write_reg(reg_isr, read_reg(reg_isr));		write_reg(reg_status, 0);				iface->data = pmsg->buf;		iface->datalen = pmsg->len;		iface->state = state_addr;		iface->result = 0;		iface->stopretry = 0;		if (pmsg->flags & I2C_M_RD)			iface->read_write = I2C_SMBUS_READ;		else			iface->read_write = I2C_SMBUS_WRITE;		/* Set up address and r/w bit */		if (pmsg->flags & I2C_M_REV_DIR_ADDR)			addr ^= 1;				write_reg(reg_addr,			(addr << 1) |			((iface->read_write == I2C_SMBUS_READ) ? 0x01 : 0x00));		/* Arm timeout */		iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;		add_timer(&iface->timeout_timer);		/* Start sending address & enable interrupt*/		write_reg(reg_control, read_reg(reg_control) | KW_I2C_CTL_XADDR);		write_reg(reg_ier, KW_I2C_IRQ_MASK);#ifdef POLLED_MODE		DBG("using polled mode...\n");		/* State machine, to turn into an interrupt handler */		while(iface->state != state_idle) {			u8 isr = wait_interrupt(iface);			handle_interrupt(iface, isr);		}#else /* POLLED_MODE */88		DBG("using interrupt mode...\n");		wait_for_completion(&iface->complete);	#endif /* POLLED_MODE */			rc = iface->result;		if (rc == 0)			completed++;		DBG("transfer done, result: %d\n", rc);	}	/* Release sem */	up(&iface->sem);	return completed;}static u32keywest_func(struct i2c_adapter * adapter){	return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |	       I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |	       I2C_FUNC_SMBUS_BLOCK_DATA;}static voidkeywest_inc(struct i2c_adapter *adapter){	MOD_INC_USE_COUNT;}static voidkeywest_dec(struct i2c_adapter *adapter){	MOD_DEC_USE_COUNT;}/* For now, we only handle combined mode (smbus) */static struct i2c_algorithm keywest_algorithm = {	name:		"Keywest i2c",	id:		I2C_ALGO_SMBUS,	smbus_xfer:	keywest_smbus_xfer,	master_xfer:	keywest_xfer,	functionality:	keywest_func,};static intcreate_iface(struct device_node* np){	unsigned long steps, *psteps, *prate;	unsigned bsteps, tsize, i, nchan, addroffset;	struct keywest_iface* iface;	int rc;	psteps = (unsigned long *)get_property(np, "AAPL,address-step", NULL);	steps = psteps ? (*psteps) : 0x10;	/* Hrm... maybe we can be smarter here */	for (bsteps = 0; (steps & 0x01) == 0; bsteps++)		steps >>= 1;	if (!strcmp(np->parent->name, "uni-n")) {		nchan = 2;		addroffset = 3;	} else {		addroffset = 0;		nchan = 1;	}	tsize = sizeof(struct keywest_iface) +		(sizeof(struct keywest_chan) + 4) * nchan;	iface = (struct keywest_iface *) kmalloc(tsize, GFP_KERNEL);	if (iface == NULL) {		printk(KERN_ERR "i2c-keywest: can't allocate inteface !\n");		return -ENOMEM;	}	memset(iface, 0, tsize);	init_MUTEX(&iface->sem);	spin_lock_init(&iface->lock);	init_completion(&iface->complete);	iface->bsteps = bsteps;	iface->chan_count = nchan;	iface->state = state_idle;	iface->irq = np->intrs[0].line;	iface->channels = (struct keywest_chan *)		(((unsigned long)(iface + 1) + 3UL) & ~3UL);	iface->base = (unsigned long)ioremap(np->addrs[0].address + addroffset,						np->addrs[0].size);	if (iface->base == 0) {		printk(KERN_ERR "i2c-keywest: can't map inteface !\n");		kfree(iface);		return -ENOMEM;	}	init_timer(&iface->timeout_timer);	iface->timeout_timer.function = keywest_timeout;	iface->timeout_timer.data = (unsigned long)iface;	/* Select interface rate */	iface->cur_mode = KW_I2C_MODE_100KHZ;	prate = (unsigned long *)get_property(np, "AAPL,i2c-rate", NULL);	if (prate) switch(*prate) {	case 100:		iface->cur_mode = KW_I2C_MODE_100KHZ;		break;	case 50:		iface->cur_mode = KW_I2C_MODE_50KHZ;		break;	case 25:		iface->cur_mode = KW_I2C_MODE_25KHZ;		break;	default:		printk(KERN_WARNING "i2c-keywest: unknown rate %ldKhz, using 100KHz\n",			*prate);	}		/* Select standard sub mode */	iface->cur_mode |= KW_I2C_MODE_STANDARDSUB;		/* Write mode */	write_reg(reg_mode, iface->cur_mode);		/* Switch interrupts off & clear them*/	write_reg(reg_ier, 0x00);	write_reg(reg_isr, KW_I2C_IRQ_MASK);#ifndef POLLED_MODE	/* Request chip interrupt */		rc = request_irq(iface->irq, keywest_irq, 0, "keywest i2c", iface);	if (rc) {		printk(KERN_ERR "i2c-keywest: can't get IRQ %d !\n", iface->irq);		iounmap((void *)iface->base);		kfree(iface);		return -ENODEV;	}#endif /* POLLED_MODE */	for (i=0; i<nchan; i++) {		struct keywest_chan* chan = &iface->channels[i];		u8 addr;				sprintf(chan->adapter.name, "%s %d", np->parent->name, i);		chan->iface = iface;		chan->chan_no = i;		chan->adapter.id = I2C_ALGO_SMBUS;		chan->adapter.algo = &keywest_algorithm;		chan->adapter.algo_data = NULL;		chan->adapter.inc_use = keywest_inc;		chan->adapter.dec_use = keywest_dec;		chan->adapter.client_register = NULL;		chan->adapter.client_unregister = NULL;		chan->adapter.data = chan;		rc = i2c_add_adapter(&chan->adapter);		if (rc) {			printk("i2c-keywest.c: Adapter %s registration failed\n",				chan->adapter.name);			chan->adapter.data = NULL;		}		if (probe) {			printk("Probe: ");			for (addr = 0x00; addr <= 0x7f; addr++) {				if (i2c_smbus_xfer(&chan->adapter,addr,				    0,0,0,I2C_SMBUS_QUICK,NULL) >= 0)					printk("%02x ", addr);			}			printk("\n");		}	}	printk(KERN_INFO "Found KeyWest i2c on \"%s\", %d channel%s, stepping: %d bits\n",		np->parent->name, nchan, nchan > 1 ? "s" : "", bsteps);			iface->next = ifaces;	ifaces = iface;	return 0;}static voiddispose_iface(struct keywest_iface *iface){	int i, rc;		ifaces = iface->next;	/* Make sure we stop all activity */	down(&iface->sem);#ifndef POLLED_MODE	spin_lock_irq(&iface->lock);	while (iface->state != state_idle) {		spin_unlock_irq(&iface->lock);		schedule();		spin_lock_irq(&iface->lock);	}#endif /* POLLED_MODE */	iface->state = state_dead;#ifndef POLLED_MODE	spin_unlock_irq(&iface->lock);	free_irq(iface->irq, iface);#endif /* POLLED_MODE */	up(&iface->sem);	/* Release all channels */	for (i=0; i<iface->chan_count; i++) {		struct keywest_chan* chan = &iface->channels[i];		if (!chan->adapter.data)			continue;		rc = i2c_del_adapter(&chan->adapter);		chan->adapter.data = NULL;		/* We aren't that prepared to deal with this... */		if (rc)			printk("i2c-keywest.c: i2c_del_adapter failed, that's bad !\n");	}	iounmap((void *)iface->base);	kfree(iface);}static int __initi2c_keywest_init(void){	struct device_node *np;	int rc = -ENODEV;		np = find_compatible_devices("i2c", "keywest");	while (np != 0) {		if (np->n_addrs >= 1 && np->n_intrs >= 1)			rc = create_iface(np);		np = np->next;	}	if (ifaces)		rc = 0;	return rc;}static void __exiti2c_keywest_cleanup(void){	while(ifaces)		dispose_iface(ifaces);}module_init(i2c_keywest_init);module_exit(i2c_keywest_cleanup);

⌨️ 快捷键说明

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