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

📄 em8xxx_i2c.c

📁 Sigma SMP8634 Mrua v. 2.8.2.0
💻 C
字号:
/***************************************** Copyright © 2007 Sigma Designs, Inc. Proprietary and Confidential *****************************************//**  @file   em8xxx_i2c.c  @brief    I2C driver for the EM8xxx series.  Strategy :    @author Alan Hightower - Wegener Communications, Inc  @date   2007-04-21*/#ifndef __I2CEM8XXX_C__#define __I2CEM8XXX_C__#define ALLOW_OS_CODE 1#include "../../../emhwlib/include/emhwlib.h"#include "../../../emhwlib/include/emhwlib_properties_1000.h"#include "../../../emhwlib/include/emhwlib_chipspecific.h"#include <linux/init.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/config.h>#include <linux/stddef.h>#include <linux/version.h>#include <linux/fs.h>#include <linux/sched.h>#include <linux/interrupt.h>#include <linux/i2c.h>#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)#include <linux/moduleparam.h>#endif#include "../../../llad/kinclude/kernelcalls.h"#include "../include/em8xxx_uk.h"#include "em8xxx.h"#include "em8xxx_proc.h"#include "../../../gbuslib/include/gbus_time.h"typedef struct _st_i2cprivate{	/**	 * Whether the I2C module for this chip has been started	 */	int active;	/**	 * Chip number for this context info block (index into	 * this i2cinfo array)	 */	int instance;	/**	 * I2C subsystem adpater instance information for this	 * chip's bus	 */	struct i2c_adapter adapter;} i2cprivate_t;static i2cprivate_t i2cinfo[MAXLLAD];#define	I2C_CLOCK_LINE    GPIOId_Sys_0#define	I2C_DATA_LINE     GPIOId_Sys_1#define	I2C_API_VERSION   1// uSec delay between bits in i2c#define	I2C_DEFAULT_BIT_DELAY    10// frequency of the I2C bit transfer, in kHz#define	I2C_DEFAULT_CLOCK_RATE   100static int i2c_bit_delay = I2C_DEFAULT_BIT_DELAY;static int i2c_clock_rate = I2C_DEFAULT_CLOCK_RATE;module_param(i2c_bit_delay, int, 0);module_param(i2c_clock_rate, int, 0);MODULE_PARM_DESC(i2c_bit_delay, "Delay between bits (default " __MODULE_STRING(I2C_DEFAULT_BIT_DELAY) " uSecs).");MODULE_PARM_DESC(i2c_clock_rate, "Bus clock rate (default " __MODULE_STRING(I2C_DEFAULT_CLOCK_RATE) " kHz).");extern struct em8xxxprivate Etable[MAXLLAD];MODULE_DESCRIPTION("EM8XXX I2C SMBus Driver");MODULE_AUTHOR("Alan Hightower <alan@alanlee.org>");MODULE_LICENSE("Proprietary");static int sigma_i2c_master(	struct i2c_adapter *adap,	struct i2c_msg *msgs,	int num){	i2cprivate_t *info = (i2cprivate_t *) adap->algo_data;	struct i2c_msg *pmsg;	int i, completed = 0;	RMstatus err;	struct EMhwlibI2CDeviceParameter i2c;	struct I2C_WriteData_type i2c_write;	struct I2C_QueryData_in_type i2c_param;	struct I2C_QueryData_out_type i2c_res;	for (i = 0; i < num; i++)	{		pmsg = &msgs[i];#ifdef I2C_DEBUG_BUS		dev_info (&adap->dev, "I2C transaction setup: "		          "%s %d bytes to 0x%02x - %d of %d messages\n",		          pmsg->flags & I2C_M_RD ? "read" : "write",		          pmsg->len, pmsg->addr, i + 1, num);#endif		// Setup transaction		i2c.APIVersion = I2C_API_VERSION;		i2c.Clock      = I2C_CLOCK_LINE;		i2c.Data       = I2C_DATA_LINE;		i2c.Delay      = i2c_bit_delay;		i2c.Speed      = i2c_clock_rate;		i2c.DevAddr    = pmsg->addr << 1;#if 0		if (pmsg->flags & I2C_M_RD)			i2c.DevAddr |= 0x01;#endif		kc_spin_lock_bh (Etable[info->instance].lock);		err = EMhwlibSetProperty (Etable[info->instance].pemhwlib,		                          EMHWLIB_MODULE(I2C, 0),		                          RMI2CPropertyID_DeviceParameter,		                          &i2c, sizeof(i2c));		kc_spin_unlock_bh (Etable[info->instance].lock);		if (RMFAILED(err))		{			dev_err (&adap->dev, "Unable to set device xfer parameters\n");			continue;		}		if (pmsg->flags & I2C_M_RD)		{			i2c_param.UseSubAddr = 0;			i2c_param.SubAddr    = 0;			i2c_param.DataSize   = pmsg->len;			kc_spin_lock_bh (Etable[info->instance].lock);			err = EMhwlibExchangeProperty(Etable[info->instance].pemhwlib,			                              EMHWLIB_MODULE(I2C, 0),			                              RMI2CPropertyID_QueryData,			                              &i2c_param, sizeof(i2c_param), 			                              &i2c_res, sizeof(i2c_res));			kc_spin_unlock_bh (Etable[info->instance].lock);			if (RMFAILED(err))			{				dev_err (&adap->dev, "Unable to perform I2C read - %d\n", err);				continue;			}			memcpy (pmsg->buf, i2c_res.Data, pmsg->len);		}		else		{			i2c_write.UseSubAddr = 0;			i2c_write.SubAddr    = 0;			i2c_write.DataSize   = pmsg->len;			memcpy (i2c_write.Data, pmsg->buf, pmsg->len);			kc_spin_lock_bh (Etable[info->instance].lock);			err = EMhwlibSetProperty(Etable[info->instance].pemhwlib,			                         EMHWLIB_MODULE(I2C, 0),			                         RMI2CPropertyID_WriteData,			                         &i2c_write, sizeof(i2c_write));			kc_spin_unlock_bh (Etable[info->instance].lock);			if (RMFAILED(err))			{				dev_err (&adap->dev, "Unable to perform I2C write\n");				continue;			}		}#ifdef I2C_DEBUG_BUS		dev_info (&adap->dev, "I2C transaction completed successfully\n");#endif	}	return completed;} // end of "sigma_i2c_master ()"static int sigma_i2c_smbus(	struct i2c_adapter *adap,	u16 addr,	unsigned short flags,	char read_write,	u8 command,	int size,	union i2c_smbus_data *data){	int usesub;	int datalen = 0;	RMstatus err;	i2cprivate_t *info = (i2cprivate_t *) adap->algo_data;	struct EMhwlibI2CDeviceParameter i2c;	struct I2C_WriteData_type i2c_write;	struct I2C_QueryData_in_type i2c_param;	struct I2C_QueryData_out_type i2c_res;#ifdef I2C_DEBUG_BUS	dev_info(&adap->dev, "%s was called with the following parameters:\n",		    __FUNCTION__);	dev_info(&adap->dev, "addr = %.4x\n", addr);	dev_info(&adap->dev, "flags = %.4x\n", flags);	dev_info(&adap->dev, "read_write = %s\n",		    read_write == I2C_SMBUS_WRITE ? "write" : "read");	dev_info(&adap->dev, "command = %d\n", command);#endif		switch (size)	{	case I2C_SMBUS_QUICK:#ifdef I2C_DEBUG_BUS		dev_info(&adap->dev, "size = I2C_SMBUS_QUICK (0)\n");#endif		usesub = FALSE;		datalen = 0;		break;	case I2C_SMBUS_BYTE:#ifdef I2C_DEBUG_BUS		dev_info(&adap->dev, "size = I2C_SMBUS_BYTE (1)\n");#endif		usesub = FALSE;		datalen = 1;		if (read_write == I2C_SMBUS_WRITE)			i2c_write.Data[0] = data ? data->byte : 0x00;		break;	case I2C_SMBUS_BYTE_DATA:#ifdef I2C_DEBUG_BUS		dev_info(&adap->dev, "size = I2C_SMBUS_BYTE_DATA (1)\n");#endif		usesub = TRUE;		datalen = 1;		if (read_write == I2C_SMBUS_WRITE)			i2c_write.Data[0] = data->byte;		break;	case I2C_SMBUS_WORD_DATA:#ifdef I2C_DEBUG_BUS		dev_info(&adap->dev, "size = I2C_SMBUS_WORD_DATA (2)\n");#endif		usesub = TRUE;		datalen = 2;		if (read_write == I2C_SMBUS_WRITE)		{			i2c_write.Data[0] = data->word & 0xff;			i2c_write.Data[1] = (data->word >> 8) & 0xff;		}		break;	case I2C_SMBUS_BLOCK_DATA:		usesub = TRUE;		datalen = min_t(u8, data->block[0], 32);		if (read_write == I2C_SMBUS_WRITE)			memcpy (i2c_write.Data, &data->block[1], datalen);#ifdef I2C_DEBUG_BUS		dev_info(&adap->dev, "size = I2C_SMBUS_BLOCK_DATA (%d)\n", datalen);#endif		break;	case I2C_SMBUS_I2C_BLOCK_DATA:		usesub = TRUE;		if (read_write == I2C_SMBUS_WRITE)		{			memcpy (i2c_write.Data, &data->block[1], datalen);			datalen = data->block[0];		}		else			data->block[0] = datalen = 32;#ifdef I2C_DEBUG_BUS		dev_info(&adap->dev, "size = I2C_SMBUS_I2C_BLOCK_DATA (%d)\n", datalen);#endif		break;	default:		goto exit_unsupported;	}	// Setup transaction	i2c.APIVersion = I2C_API_VERSION;	i2c.Clock      = I2C_CLOCK_LINE;	i2c.Data       = I2C_DATA_LINE;	i2c.Delay      = i2c_bit_delay;	i2c.Speed      = i2c_clock_rate;	i2c.DevAddr    = addr << 1;#if 0	if (read_write == I2C_SMBUS_READ)		i2c.DevAddr |= 0x01;#endif	kc_spin_lock_bh (Etable[info->instance].lock);	err = EMhwlibSetProperty (Etable[info->instance].pemhwlib,	                          EMHWLIB_MODULE(I2C, 0),	                          RMI2CPropertyID_DeviceParameter,	                          &i2c, sizeof(i2c));	kc_spin_unlock_bh (Etable[info->instance].lock);	if (RMFAILED(err))	{		dev_err (&adap->dev, "Unable to set device xfer parameters"		         " (addr=0x%04x)\n", addr);		return -EINVAL;	}#ifdef I2C_DEBUG_BUS	dev_info(&adap->dev, "Transaction setup complete\n");#endif	if (read_write == I2C_SMBUS_READ)	{		i2c_param.UseSubAddr = usesub ? 1 : 0;		i2c_param.SubAddr    = command;		i2c_param.DataSize   = datalen;		kc_spin_lock_bh (Etable[info->instance].lock);		err = EMhwlibExchangeProperty(Etable[info->instance].pemhwlib,		                              EMHWLIB_MODULE(I2C, 0),		                              RMI2CPropertyID_QueryData, 		                              &i2c_param, sizeof(i2c_param), 		                              &i2c_res, sizeof(i2c_res));		kc_spin_unlock_bh (Etable[info->instance].lock);		if (RMFAILED(err))		{			dev_err (&adap->dev, "Unable to perform I2C read - %d\n", err);			return -EINVAL;		}		switch (size)		{		case I2C_SMBUS_BYTE:		case I2C_SMBUS_BYTE_DATA:			data->byte = i2c_res.Data[0];			break;		case I2C_SMBUS_WORD_DATA:			data->word = i2c_res.Data[0] + (i2c_res.Data[0] << 8);			break;		case I2C_SMBUS_BLOCK_DATA:		case I2C_SMBUS_I2C_BLOCK_DATA:			memcpy (&data->block[1], i2c_res.Data, datalen);			break;		}	}	else	{		i2c_write.UseSubAddr = usesub;		i2c_write.SubAddr    = command;		i2c_write.DataSize   = datalen;		kc_spin_lock_bh (Etable[info->instance].lock);		err = EMhwlibSetProperty(Etable[info->instance].pemhwlib,		                         EMHWLIB_MODULE(I2C, 0),		                         RMI2CPropertyID_WriteData,		                         &i2c_write, sizeof(i2c_write));		kc_spin_unlock_bh (Etable[info->instance].lock);		if (RMFAILED(err))		{			dev_err (&adap->dev, "Unable to perform I2C write\n");			return -EINVAL;		}	}	return 0;exit_unsupported:	dev_warn (&adap->dev, "Unsupported command invoked! (0x%02x)\n", size);	return -EINVAL;} // end of "sigma_i2c_smbus ()"static u32 sigma_i2c_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 |	       I2C_FUNC_SMBUS_I2C_BLOCK;}static struct i2c_algorithm sigma_i2c_algorithm = {	.smbus_xfer	= sigma_i2c_smbus,	.master_xfer   = sigma_i2c_master,	.functionality	= sigma_i2c_func,};int __init init_module (void){	int i, rc;	printk ("em8xxxi2c init begin (bit delay = %d uSec / clock rate = %d KHz)\n",	        i2c_bit_delay, i2c_clock_rate);	for (i = 0 ; i < MAXLLAD; i++)	{		if ((&Etable[i])->pllad != NULL)		{			memset (&i2cinfo[i], 0, sizeof (i2cprivate_t));			i2cinfo[i].adapter.owner     = THIS_MODULE;			i2cinfo[i].adapter.class     = I2C_CLASS_HWMON;			i2cinfo[i].adapter.algo      = &sigma_i2c_algorithm;			i2cinfo[i].adapter.algo_data = &i2cinfo[i];			strncpy (i2cinfo[i].adapter.name, "Sigma I2C Driver", I2C_NAME_SIZE - 1);			rc = i2c_add_adapter (&i2cinfo[i].adapter);			if (rc < 0)			{				printk ("Unable to register i2c driver for chip %d\n", i);			}			else			{				printk ("Registered I2C driver for chip %d\n", i);				i2cinfo[i].active = TRUE;				i2cinfo[i].instance = i;			}		}	}		printk ("em8xxxi2c init end\n");		return 0;	} // end of "init_module ()"void __exit cleanup_module (void){	int i;		printk ("em8xxxi2c cleanup begin\n");	for (i = 0 ; i < MAXLLAD ; i++)	{		if (i2cinfo[i].active)		{			i2c_del_adapter (&i2cinfo[i].adapter);		}	}		printk ("em8xxxi2c cleanup end\n");	return;} // end of "cleanup_module ()"#endif // __I2CEM8XXX_C__

⌨️ 快捷键说明

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