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

📄 i2c-aa.c

📁 Dragonball I2C驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************	Copyright (C) 2002 Motorola GSG-China	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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.*******************************************************************************//************************************************************************ *  File Name : i2c-aa.c *  Description : *	Implementation of i2c Adapter/Algorithm Driver *  Auther *  History: *  	2002/2/7 use msgs[] *  Data *  ID ************************************************************************/#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/uaccess.h>#include <linux/ioport.h>#include <linux/errno.h>#include <linux/sched.h>#include <linux/hfs_sysdep.h>#include <linux/i2c.h>#include <linux/i2c-algo-bit.h>#include <linux/i2c-id.h>#include "i2c-aa.h"#include <asm/irq.h>#define POLLING_MODE/************************************************************************ * 	Globel Variable Define ************************************************************************/ 	static struct I2C_AA_REG *i2c_aa_reg = (struct I2C_AA_REG *)I2C_AA_REG_ADDR;#define i2c_aa_stop() i2c_aa_reg->i2cr &= ~(0x20)#define i2c_aa_repeat_start() i2c_aa_reg->i2cr |= 0x04void i2c_aa_bus_release(void);#if (LINUX_VERSION_CODE < 0x020301)static struct wait_queue *aa_wait = NULL;#elsestatic wait_queue_head_t aa_wait;#endifSINT16 __init i2c_aa_init(void);void __exit i2c_aa_cleanup(void);static void i2c_aa_inc(struct i2c_adapter *adap);static void i2c_aa_dec(struct i2c_adapter *adap);int i2c_aa_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[ ], int num);int i2c_smbus_aa_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data * data);#ifndef POLLING_MODEstatic void i2c_aa_isr (SINT16 irq, void * dev_id, struct pt_regs * reg);#endifint i2c_aa_ioctl(struct i2c_adapter * adapter, unsigned int cmd, unsigned long arg);static struct i2c_algorithm i2c_aa_algorithm = {	/* name */		"DBMX1 I2C A/A",	/* id: */		I2C_ALGO_BIT,	/* master_xfer:*/	i2c_aa_xfer,	/* smbus_xfer: */	i2c_smbus_aa_xfer,	/* slave_send: */	NULL,	/* slave_recv: */	NULL,	/* algo_control: */	i2c_aa_ioctl,	/* functionality: */	NULL};	static struct i2c_adapter i2c_mx1_adapter = {	/* name: */				"DBMX1 I2C adapter",	/* id = algo->id | hwdep.struct->id */	I2C_ALGO_BIT | I2C_HW_B_SER,		/* i2c_algorithm: */			&i2c_aa_algorithm,	/* algo_data */				NULL,	/* inc_use */				i2c_aa_inc,	/* dec_use */				i2c_aa_dec,	/* client_regester */			NULL,	/* client_unregister */ 		NULL};/* return 1 : bus is idle/stop signal is detect , and Arbitration Lost * return 0 : bus is busy/start signal is detect */int i2c_aa_bus_grab(void){	unsigned int val;	while(!((val = i2c_aa_reg->i2sr) & (UINT32)0x20))	{		if ( val & 0x10)		{			return 1;		}	}	return 0;}int i2c_aa_start(){	/* Set Master Mode and signal a start bit */	//printk(" i2c_aa_start starts \n");	i2c_aa_reg->i2cr |= 0x20;	while(i2c_aa_bus_grab()){		//printk(" enter i2c_aa_bus_grab \n");		i2c_aa_stop();		i2c_aa_bus_release();		/*	check IBB[I2SR:5] (I2C bus busy bit) until it is not busy *******/ 		while((i2c_aa_reg->i2sr) & (UINT32)0x20);		/*	set IEN[I2CR:7] (I2C Enable)	*********************************/		i2c_aa_reg->i2cr |= (UINT32)0x80;		/* Set the TXAK[I2CR:6] to disable the I2C transmit ACK *****************/		i2c_aa_reg->i2cr |= (UINT32)0x08;		i2c_aa_reg->i2cr |= 0x20;	}	//printk(" i2c_aa_start ends \n");	return 0;}/* return when a stop signal is detect */void i2c_aa_bus_release(void){		short int i=0;	int dummy;	while((i2c_aa_reg->i2sr & (UINT32)0x20)&& i<1000){		i++;		if (i==999){			/*Reset the module process suggested in reference manual (tahiti)*/			i2c_aa_reg->i2cr = (UINT32)0x00;			i2c_aa_reg->i2cr |= (UINT32)0x0A;			dummy = (UINT8)i2c_aa_reg->i2dr;			i2c_aa_reg->i2sr = (UINT32)0x00;			i2c_aa_reg->i2cr = (UINT32)0x00;		}			//printk("wait for the bus release command\n");	}}/* wait until the interrupt pending then , clear IIF[I2SR:1] */void i2c_aa_transfer_complete(void){	while(!(i2c_aa_reg->i2sr & (UINT32)0x02));	i2c_aa_reg->i2sr &= ~(UINT32)0x02;}/* wait until MX1 received the acknowledge *///This Funtion will hand the MX1, dont know why//LEOvoid i2c_aa_received_acknowledge(void){	while(i2c_aa_reg->i2sr & (UINT32)0x01);}void test(void){	unsigned int value;		printk("<1>--------------------------------------\n");	value = READREG(IFDR);	printk("<1>IFDR: 0x%x\n", value);	value = READREG(I2CR);	printk("<1>I2CR: 0x%x\n", value);	value = READREG(I2SR);	printk("<1>I2SR: 0x%x\n", value);	printk("<1>--------------------------------------\n");}/************************************************************************ * 	I2C_AA Driver ************************************************************************/ 	void i2c_aa_inc(struct i2c_adapter *adap){	FUNC_START;	MOD_INC_USE_COUNT;	FUNC_END;}void i2c_aa_dec(struct i2c_adapter *adap){	FUNC_START;	MOD_DEC_USE_COUNT;	FUNC_END;}#ifndef POLLING_MODE#include "i2c_rw.h"#endif/*----------------------------------------------------------------------- * SINT16 __init i2c_aa_init(void) * initializes the I2C module in the DBMX1, and registers itself to the  * Linux I2C system * * Parameters: * 	None * Return: * 	0	indicates SUCCESS * 	-1	indicates FAILURE * --------------------------------------------------------------------*/SINT16 __init i2c_aa_init(void){	int tmp;	tmp = 0;	FUNC_START;	/* 	 * port enable for I2c signal 	 * PA15 : I2C_DATA	 * PA16 : I2C_CLK	 */#ifdef POLLING_MODE	MX1_REG_PTA_DDIR |=  0x00018000;	MX1_REG_PTA_GIUS &= ~0x00018000;#else	MX1_REG_PTA_DDIR |=  0x00018000;	MX1_REG_PTA_GIUS &= ~0x00018000;	//MX1_REG_PTA_GPR  &= ~0x00018000;	//MX1_REG_PTA_PUEN &= ~0x00018000;#endif		/* Init queue */#if (LINUX_VERSION_CODE >= 0x020301)	init_waitqueue_head(&aa_wait);#endif	/* add the I2C adapter/algorithm driver to the linux kernel */	if (i2c_add_adapter(&i2c_mx1_adapter))	{		CSI_LOC;		return -1;	}#ifndef POLLING_MODE	/* install the I2C_AA ISR to the Linux Kernel */	tmp = request_irq(I2C_AA_IRQ,		    (void *)i2c_aa_isr,//		    SA_SHIRQ | SA_INTERRUPT,			SA_INTERRUPT,		    "I2C_AA",		    "i2c_bus");	if (tmp < 0)		i2c_del_adapter(&i2c_mx1_adapter);	enable_irq(I2C_AA_IRQ);	IOW(0x223008, I2C_AA_IRQ); // enable #endif	/* Set clock Freq. */	i2c_aa_reg->ifdr = (UINT32)DEFAULT_FREQ;	FUNC_END;	return tmp;}/* SMbus Xfer Data */int i2c_smbus_aa_xfer(struct i2c_adapter * adapter, u16 addr,                                    unsigned short flags,                                   char read_write, u8 command, int size,                                    union i2c_smbus_data * data){	/* So we need to generate a series of msgs. In the case of writing, we	  need to use only one message; when reading, we need two. We initialize	  most things with sane defaults, to keep the code below somewhat	  simpler. */	  	struct i2c_msg msg[2];	  	char keybuf[2];		keybuf[0] = 0;		keybuf[1] = 0;		msg[0].addr = addr;		//msg[0].addr &= 0xFFFE;		msg[0].flags = 0x00;		msg[0].len = 1;		msg[0].buf = &command;				msg[1].addr = addr;		//msg[1].addr &= 0xFFFE;		msg[1].flags = I2C_M_RD;		msg[1].len = 2;		msg[1].buf = keybuf;		printk("good\n");		i2c_transfer(adapter, msg, 2 );		data->word = keybuf[0] | (keybuf[1] << 8);		return 0;#if 0	char msgbuf0[34];	char msgbuf1[34];	int num = read_write == I2C_SMBUS_READ?2:1;	struct i2c_msg msg[2] = { { addr, flags, 1, msgbuf0 }, 	                          { addr, flags | I2C_M_RD, 0, msgbuf1 }	                        };	int i;	printk("Enter i2c_smbus_aa_xfer\n");	msgbuf0[0] = command;	switch(size) {	case I2C_SMBUS_QUICK:		msg[0].len = 0;		/* Special case: The read/write field is used as data */		msg[0].flags = flags | (read_write==I2C_SMBUS_READ)?I2C_M_RD:0;		num = 1;		break;	case I2C_SMBUS_BYTE:		if (read_write == I2C_SMBUS_READ) {			/* Special case: only a read! */			msg[0].flags = I2C_M_RD | flags;			num = 1;		}		break;

⌨️ 快捷键说明

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