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

📄 i2c-omaha.c

📁 linux 下的i2c驱动程序
💻 C
字号:
/* ------------------------------------------------------------------------- *    Copyright ARM Limited 2002. All rights reserved.     i2c driver for Omaha					          Notes:Based on i2c-elv.c     The S3C2400X01 has better support for I2C, but bit oriented operations     are directly supported by the other I2C layers, so we use that method    of performing I2C operations.    Copyright (C) 1995-2000 Simon G. Vogl    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; if not, write to the Free Software    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.		     *//* ------------------------------------------------------------------------- */#include <linux/kernel.h>#include <linux/module.h>#include <linux/delay.h>#include <linux/slab.h>#include <linux/version.h>#include <linux/init.h>#include <asm/irq.h>#include <asm/io.h>#include <asm/uaccess.h>#include <linux/ioport.h>#include <linux/errno.h>#include <linux/sched.h>#include <linux/i2c.h>#include <linux/i2c-algo-bit.h>#include <asm/io.h>#include <asm/hardware.h>/* ----- global defines ----------------------------------------------- */#define DEB(x) if (i2c_debug>=1) x;#define DEB2(x) if (i2c_debug>=2) x;#define DEB3(x) if (i2c_debug>=3) x#define DEBE(x)	x	// error messages#define DEBSTAT(x) if (i2c_debug>=3) x; /* print several statistical values*/#define DEBPROTO(x) if (i2c_debug>=9) { x; } 	/* debug the protocol by showing transferred bits *//* Register and bitdefs for Omaha */// Port G control registersstatic volatile unsigned int pgcon = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_PGCON);static volatile unsigned int pgdat = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_PGDAT);static volatile unsigned int opencr = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_OPENCR);static int base = IO_ADDRESS(PLAT_PERIPHERAL_BASE+OMAHA_PGCON);// Open drain control registers#define OPC_CMD		BIT2#define OPC_DAT		BIT3// data bits in GPIO Port G data register#define OMAHA_SDA	BIT5#define OMAHA_SCL	BIT6#define IIC_WP		BIT3	// Write Protect for EEPROM// input/out select bits in GPIO G control register#define IIC_BITS	(BIT12|BIT10|BIT6);/* ----- local functions ----------------------------------------------	*/static void bit_omaha_setscl(void *data, int state){	unsigned int tmp;		if (state)	{		tmp = __raw_readl(pgdat);		tmp |= OMAHA_SCL;		__raw_writel(tmp,pgdat);	}	else	{		tmp = __raw_readl(pgdat);		tmp &= ~OMAHA_SCL;		__raw_writel(tmp,pgdat);	}}static void bit_omaha_setsda(void *data, int state){	unsigned int tmp;		// ensure that sda is an output at the moment	tmp = __raw_readl(pgcon);	tmp = tmp | BIT10;	__raw_writel(tmp,pgcon);			if (state)	{		tmp = __raw_readl(pgdat);		tmp |= OMAHA_SDA;		__raw_writel(tmp,pgdat);	}	else	{		tmp = __raw_readl(pgdat);		tmp &= ~OMAHA_SDA;		__raw_writel(tmp,pgdat);	}} static int bit_omaha_getscl(void *data){	if (__raw_readl(pgdat) & OMAHA_SCL)		return 1;	else		return 0;}static int bit_omaha_getsda(void *data){	unsigned int tmp;		// ensure that sda is an output at the moment	tmp = __raw_readl(pgcon);	tmp = tmp & ~BIT10;	__raw_writel(tmp,pgcon);		if (__raw_readl(pgdat) & OMAHA_SDA)		return 1;	else		return 0;}static int bit_omaha_init(void){	// Have we got some mmapped space?	if (request_region(base, 0x100, "i2c (omaha bus adapter)") < 0 )	{		printk("i2c-omaha.o: requested I/O region (0x%08x) is in use.\n", base);		return -ENODEV;	}	return 0;}static int bit_omaha_reg(struct i2c_client *client){	return 0;}static int bit_omaha_unreg(struct i2c_client *client){	return 0;}static void bit_omaha_inc_use(struct i2c_adapter *adap){	MOD_INC_USE_COUNT;}static void bit_omaha_dec_use(struct i2c_adapter *adap){	MOD_DEC_USE_COUNT;}/* ------------------------------------------------------------------------ * Encapsulate the above functions in the correct operations structure. * This is only done when more than one hardware adapter is supported. */static struct i2c_algo_bit_data bit_omaha_data = {	NULL,	bit_omaha_setsda,	bit_omaha_setscl,	bit_omaha_getsda,	bit_omaha_getscl,	10, 10, 20,		/*	waits, timeout */};static struct i2c_adapter bit_omaha_ops = {	"BIT-Type Omaha I2C adapter",	I2C_HW_B_OMAHA,	NULL,	&bit_omaha_data,	bit_omaha_inc_use,	bit_omaha_dec_use,	bit_omaha_reg,	bit_omaha_unreg,};     static int __init i2c_omaha_init (void){	unsigned int tmp;	printk("i2c-omaha.o: i2c omaha adapter module\n");		if (bit_omaha_init() == 0) {		if(i2c_bit_add_bus(&bit_omaha_ops) < 0)		{			printk("Could not add bus!\n");			return -ENODEV;		}	} else {		printk("Could not pcf_omaha_init\n");		return -ENODEV;	}			// Program Port G bits to output function	tmp = __raw_readl(pgcon);	tmp |= IIC_BITS;	   		__raw_writel(tmp,pgcon);		// Ensure SDA and SCL are open-drain	tmp = __raw_readl(opencr);	tmp = tmp | OPC_CMD | OPC_DAT;	__raw_writel(tmp,opencr);	bit_omaha_setsda((void*)base,1);	bit_omaha_setscl((void*)base,1);	// Disable WP	tmp = __raw_readl(pgdat);	tmp = tmp & ~IIC_WP;	__raw_writel(tmp,pgdat);			       			return 0;}static void bit_omaha_exit(void){	release_region(base , 2);}static void i2c_omaha_exit(void){	i2c_bit_del_bus(&bit_omaha_ops);	bit_omaha_exit();}EXPORT_NO_SYMBOLS;MODULE_AUTHOR("ARM Limited <support@arm.com>");MODULE_DESCRIPTION("I2C-Bus adapter routines for Omaha");MODULE_LICENSE("GPL");			MODULE_PARM(base, "i");MODULE_PARM(irq, "i");MODULE_PARM(clock, "i");MODULE_PARM(own, "i");MODULE_PARM(mmapped, "i");MODULE_PARM(i2c_debug, "i");module_init(i2c_omaha_init);module_exit(i2c_omaha_exit);

⌨️ 快捷键说明

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