微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > I2C总线驱动程序

I2C总线驱动程序

时间:11-21 来源:互联网 点击:
#include "linux/kernel.h"

#include "linux/module.h"

#include "linux/i2c.h"

#include "linux/init.h"

#include "linux/time.h"

#include "linux/interrupt.h"

#include "linux/delay.h"

#include "linux/errno.h"

#include "linux/err.h"

#include "linux/platform_device.h"

#include "linux/pm_runtime.h"

#include "linux/clk.h"

#include "linux/cpufreq.h"

#include "linux/slab.h"

#include "linux/io.h"

#include "linux/of_i2c.h"

#include "linux/of_gpio.h"

#include "plat/gpio-cfg.h"

#include "mach/regs-gpio.h"

#include "asm/irq.h"

#include "plat/regs-iic.h"

#include "plat/iic.h"

//#define PRINTK printk

#define PRINTK(...)

enum s3c24xx_i2c_state {

STATE_IDLE,

STATE_START,

STATE_READ,

STATE_WRITE,

STATE_STOP

};

struct s3c2440_i2c_regs {

unsigned int iiccon;

unsigned int iicstat;

unsigned int iicadd;

unsigned int iicds;

unsigned int iiclc;

};

struct s3c2440_i2c_xfer_data {

struct i2c_msg *msgs;

int msn_num;

int cur_msg;

int cur_ptr;

int state;

int err;

wait_queue_head_t wait;

};

static struct s3c2440_i2c_xfer_data s3c2440_i2c_xfer_data;

static struct s3c2440_i2c_regs *s3c2440_i2c_regs;

static void s3c2440_i2c_start(void)

{

s3c2440_i2c_xfer_data.state = STATE_START;

if (s3c2440_i2c_xfer_data.msgs->flags & I2C_M_RD) // 读 //

{

s3c2440_i2c_regs->iicds = s3c2440_i2c_xfer_data.msgs->addr < 1;

s3c2440_i2c_regs->iicstat = 0xb0; // 主机接收,启动

}

else // 写 //

{

s3c2440_i2c_regs->iicds = s3c2440_i2c_xfer_data.msgs->addr < 1;

s3c2440_i2c_regs->iicstat = 0xf0; // 主机发送,启动

}

}

static void s3c2440_i2c_stop(int err)

{

s3c2440_i2c_xfer_data.state = STATE_STOP;

s3c2440_i2c_xfer_data.err = err;

PRINTK("STATE_STOP, err = %d\n", err);

if (s3c2440_i2c_xfer_data.msgs->flags & I2C_M_RD) // 读 //

{

// 下面两行恢复I2C操作,发出P信号

s3c2440_i2c_regs->iicstat = 0x90;

s3c2440_i2c_regs->iiccon = 0xaf;

ndelay(50); // 等待一段时间以便P信号已经发出

}

else // 写 //

{

// 下面两行用来恢复I2C操作,发出P信号

s3c2440_i2c_regs->iicstat = 0xd0;

s3c2440_i2c_regs->iiccon = 0xaf;

ndelay(50); // 等待一段时间以便P信号已经发出

}

// 唤醒 //

wake_up(&s3c2440_i2c_xfer_data.wait);

}

static int s3c2440_i2c_xfer(struct i2c_adapter *adap,

struct i2c_msg *msgs, int num)

{

unsigned long timeout;

// 把num个msg的I2C数据发送出去/读进来 //

s3c2440_i2c_xfer_data.msgs = msgs;

s3c2440_i2c_xfer_data.msn_num = num;

s3c2440_i2c_xfer_data.cur_msg = 0;

s3c2440_i2c_xfer_data.cur_ptr = 0;

s3c2440_i2c_xfer_data.err = -ENODEV;

s3c2440_i2c_start();

// 休眠 //

timeout = wait_event_timeout(s3c2440_i2c_xfer_data.wait, (s3c2440_i2c_xfer_data.state == STATE_STOP), HZ * 5);

if (0 == timeout)

{

printk("s3c2440_i2c_xfer time out\n");

return -ETIMEDOUT;

}

else

{

return s3c2440_i2c_xfer_data.err;

}

}

static u32 s3c2440_i2c_func(struct i2c_adapter *adap)

{

return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING;

}

static const struct i2c_algorithm s3c2440_i2c_algo = {

// .smbus_xfer = ,

.master_xfer = s3c2440_i2c_xfer,

.functionality = s3c2440_i2c_func,

};

// 1. 分配/设置i2c_adapter

//

static struct i2c_adapter s3c2440_i2c_adapter = {

.name = "s3c2440_100ask",

.algo = &s3c2440_i2c_algo,

.owner = THIS_MODULE,

};

static int isLastMsg(void)

{

return (s3c2440_i2c_xfer_data.cur_msg == s3c2440_i2c_xfer_data.msn_num - 1);

}

static int isEndData(void)

{

return (s3c2440_i2c_xfer_data.cur_ptr >= s3c2440_i2c_xfer_data.msgs->len);

}

static int isLastData(void)

{

return (s3c2440_i2c_xfer_data.cur_ptr == s3c2440_i2c_xfer_data.msgs->len - 1);

}

static irqreturn_t s3c2440_i2c_xfer_irq(int irq, void *dev_id)

{

unsigned int iicSt;

iicSt = s3c2440_i2c_regs->iicstat;

if(iicSt & 0x8){ printk("Bus arbitration failed\

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top