i2c总线驱动编写:
/*
filename: I2C.c
author: pingbo an
description: EEPROM I2C
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/ioport.h>
#include <asm/io.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/of_device.h>
#include <linux/of_address.h>
#include <linux/interrupt.h>
#include <linux/workqueue.h>
#include<linux/types.h>
#include <linux/irq.h>
#include <linux/of_irq.h>
#include <linux/i2c.h>
#include <linux/completion.h>
#include <linux/clk.h>
#define EEPROM_I2C_CR_OFFSET 0x00 /* Control Register, RW */
#define EEPROM_I2C_SR_OFFSET 0x04 /*status regs*/
#define EEPROM_I2C_ISR_OFFSET 0x10 /* IRQ Status Register, RW */
#define EEPROM_I2C_ADDR_OFFSET 0x08 /*addr register*/
#define EEPROM_I2C_DATA_OFFSET 0x0C /* I2C Data Register, RW */
#define EEPROM_I2C_XFER_SIZE_OFFSET 0x14 /*recieve length register*/
#define EEPROM_I2C_IER_OFFSET 0x24 /* IRQ Enable Register, WO */
#define EEPROM_I2C_IDR_OFFSET 0x28
/* Control Register Bit mask definitions */
#define EEPROM_I2C_CR_SLVMON BIT(5) /* Slave monitor mode bit */
#define EEPROM_I2C_CR_HOLD BIT(4) /* Hold Bus bit */
#define EEPROM_I2C_CR_ACK_EN BIT(3)
#define EEPROM_I2C_CR_NEA BIT(2)
#define EEPROM_I2C_CR_MS BIT(1)
/* Read or Write Master transfer 0 = Transmitter, 1 = Receiver */
#define EEPROM_I2C_CR_RW BIT(0)
/* 1 = Auto init FIFO to zeroes */
#define EEPROM_I2C_CR_CLR_FIFO BIT(6)
#define EEPROM_I2C_DIVA_MAX 4
#define EEPROM_I2C_DIVB_MAX 64
#define EEPROM_I2C_CR_DIVA_SHIFT 14
#define EEPROM_I2C_CR_DIVA_MASK (3 << EEPROM_I2C_CR_DIVA_SHIFT)
#define EEPROM_I2C_CR_DIVB_SHIFT 8
#define EEPROM_I2C_CR_DIVB_MASK (0x3f << EEPROM_I2C_CR_DIVB_SHIFT)
#define EEPROM_I2C_TIME_OUT_OFFSET 0x1C
#define DRIVER_NAME "I2C_DRIVER"
struct eeprom_i2c_dev{
struct device *dev;
struct i2c_adapter adapter;
unsigned long size;
void __iomem *baddr;
struct i2c_msg *p_msg;
unsigned char *p_send_buf;
unsigned char *p_recv_buf;
unsigned int recv_cnt;
unsigned int send_cnt;
int hold_falg;
int irq;
struct completion msg_completion;
spinlock_t xfer_lock;
u32 i2c_clk;
u32 input_clk;
struct clk *clk;
u32 ctrl_reg;
};
static const struct of_device_id eeprom_i2c_of_match[] ={
{.compatible = "xlnx, eeprom_i2c"},
{/*end of list*/},
};
MODULE_DEVICE_TABLE(of, eeprom_i2c_of_match);
static void eeprom_i2c_mrcv(struct eeprom_i2c_dev *id){
unsigned int ctrl_reg;
unsigned int irq_status;
id->p_recv_buf=id->p_msg->buf;
id->recv_cnt=id->p_msg->len;
ctrl_reg=readl_relaxed(id->baddr+EEPROM_I2C_CR_OFFSET);
ctrl_reg |= EEPROM_I2C_CR_RW | EEPROM_I2C_CR_CLR_FIFO;
writel_relaxed(ctrl_reg, id->baddr+EEPROM_I2C_CR_OFFSET);
irq_status=readl_relaxed(id->baddr+EEPROM_I2C_ISR_OFFSET);
writel_relaxed(irq_status, id->baddr+EEPROM_I2C_ISR_OFFSET);
writel_relaxed(0x1F