linux I2C二

一、linux I2C体系结构


上图中分为用户空间部分、内核空间、硬件。

应用程序是要求实现的应用功能,通过调用系统调用(i2c-dev.c虚拟的I2C设备驱动),内核进行交互。

硬件包括实际的I2C总线和挂接在I2C总线上的设备

内核是描述设备与总线是如何通信的。

举个例子:

假设上层要给设备某地址写值,调用如下

应用层序调用系统函数write>(client)i2cdev_write->(i2c-core.c)i2c_master_send->(适配器)(adap->algo->master_xfer)->(硬件)使I2C产生特定的信号与设备交互


内核的实现:

内核分三大块 1、core   2、适配器管理+总线驱动   3、设备管理+驱动

1、core是核心模块,将适配端与外设相隔离。提供一组不依赖具体硬件的接口函数,实现各种适配器、总线驱动、设备驱动等相同的部分。一种外设可以在不同适配器上使用,一个适配器可以接不同的外设。

具体表现:

1、int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)//接收发送函数

2、int i2c_add_numbered_adapter(struct i2c_adapter *adap)//注册适配器

3、int i2c_del_adapter(struct i2c_adapter *adap)//删除适配器

。。。


2、适配器可以简单理解为cpu上的I2C接口,总线驱动是其工作软件的实现。

3、外设驱动即描述该设备怎么工作。


理解几个结构体:

struct i2c_adapter {
	struct module *owner;
	unsigned int id;
	unsigned int class;		  /* classes to allow probing for */
	const struct i2c_algorithm *algo; /* the algorithm to access the bus */
	void *algo_data;	//指向某变量或开辟的结构体

	/* data fields that are valid for all devices	*/
	struct rt_mutex bus_lock;

	int timeout;			/* in jiffies */
	int retries;			//重做次数
	struct device dev;		/* the adapter device */

	int nr;				//编号
	char name[48];		//名称
	struct completion dev_released;

	struct mutex userspace_clients_lock;
	struct list_head userspace_clients;
};

struct i2c_algorithm {//通信方法,产生特定的信号
	/* master_xfer should return the number of messages successfully
	   processed, or a negative value on error */
	int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs,
			   int num);//发送接收函数
。。。
	/* To determine what the adapter supports */
	u32 (*functionality) (struct i2c_adapter *);
。。。
}

struct i2c_driver{
unsigned int class;

	/* Notifies the driver that a new bus has appeared or is about to be
	 * removed. You should avoid using this if you can, it will probably
	 * be removed in a near future.
	 */
	int (*attach_adapter)(struct i2c_adapter *);//attach to a i2c adapter
	int (*detach_adapter)(struct i2c_adapter *);//deattach an adapter which attached

	/* Standard driver model interfaces */
	int (*probe)(struct i2c_client *, const struct i2c_device_id *);
	int (*remove)(struct i2c_client *);

	/* driver model interfaces that don't relate to enumeration  */
	void (*shutdown)(struct i2c_client *);
	int (*suspend)(struct i2c_client *, pm_message_t mesg);
	int (*resume)(struct i2c_client *);

	/* Alert callback, for example for the SMBus alert protocol.
	 * The format and meaning of the data value depends on the protocol.
	 * For the SMBus alert protocol, there is a single bit of data passed
	 * as the alert response's low bit ("event flag").
	 */
	void (*alert)(struct i2c_client *, unsigned int data);

	/* a ioctl like command that can be used to perform specific functions
	 * with the device.
	 */
	int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);

	struct device_driver driver;
	const struct i2c_device_id *id_table;

	/* Device detection callback for automatic device creation */
	int (*detect)(struct i2c_client *, struct i2c_board_info *);
	const unsigned short *address_list;
	struct list_head clients;
};

struct i2c_client {//外设描述
	unsigned short flags;		/* div., see below		*/
	unsigned short addr;		/* chip address - NOTE: 7bit	*/
					/* addresses are stored in the	*/
					/* _LOWER_ 7 bits		*/
	char name[I2C_NAME_SIZE];
	struct i2c_adapter *adapter;	/* the adapter we sit on	*/
	struct i2c_driver *driver;	/* and our access routines	*/
	struct device dev;		/* the device structure		*/
	int irq;			/* irq issued by device		*/
	struct list_head detected;
};

/*另外再了解一个重要结构体,*/
struct i2c_msg { //通信的基本载体
	__u16 addr;	/* slave address-器件地址*/
	__u16 flags;
#define I2C_M_TEN		0x0010	/* this is a ten bit chip address */
#define I2C_M_RD		0x0001	/* read data, from slave to master */
#define I2C_M_NOSTART		0x4000	/* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_REV_DIR_ADDR	0x2000	/* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_IGNORE_NAK	0x1000	/* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_NO_RD_ACK		0x0800	/* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_RECV_LEN		0x0400	/* length will be first received byte */
	__u16 len;		/* msg length--描述buf长度*/
	__u8 *buf;		/* pointer to msg data--指向数据缓存*/
};


 



现在说明如何构造i2c_msg,现以write为例说明。


    msgs[0].addr = address;
    msgs[0].flags = 0;    /* write */
    msgs[0].buf = (unsigned char *)data;//包含的数据是上图2段,本例中buf包含两个值:register address+data
    msgs[0].len = len;          //本例中len=2
    msgs[0].scl_rate = I2C_RATE;

因此,
1、系统开始时先将7位的地址左移1位,并判断msg为WRITE,所以第8位位0.
2、将地址传输出去,进入中断。在中断函数里判断传输是否正确(比如是否收到ACK信号等)
3、再依次将buf中的值发送,并用len判断是否传输完毕

现在说明如何构造i2c_msg,现以read为例说明。

分两个msg传输:
  msg0对应上图第一段,是写msg。
  msg1对应上图第二段,是读msg。

msgs[0].addr = address;//启动传输时发送
    msgs[0].flags = 0;    /* write */
    msgs[0].buf = reg;//reg表示片内地址
    msgs[0].len = 1;//发送长度
    msgs[0].scl_rate = SENSOR_I2C_RATE;
    
    msgs[1].addr = address;//重新启动后再发送(见上图段2,见下面分析)。
    msgs[1].flags = I2C_M_RD;//上图段2,第一字节第8位。
    msgs[1].buf = data;//接收缓存
    msgs[1].len = len;//接受长度
    msgs[1].scl_rate = SENSOR_I2C_RATE




按部分讲解

1、适配器

dev-i2c0.c

struct platform_device s3c_device_i2c0 = {
	.name		  = "s3c2410-i2c",
#ifdef CONFIG_S3C_DEV_I2C1
	.id		  = 0,
#else
	.id		  = -1,
#endif
	.num_resources	  = ARRAY_SIZE(s3c_i2c_resource),
	.resource	  = s3c_i2c_resource,
};

static struct s3c2410_platform_i2c default_i2c_data0 __initdata = {
	.flags		= 0,
	.slave_addr	= 0x10,
	.frequency	= 100*1000,
	.sda_delay	= 100,
};

void __init s3c_i2c0_set_platdata(struct s3c2410_platform_i2c *pd)
{
	struct s3c2410_platform_i2c *npd;

	if (!pd)
		pd = &default_i2c_data0;

	npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL);
	if (!npd)
		printk(KERN_ERR "%s: no memory for platform data\n", __func__);
	else if (!npd->cfg_gpio)
		npd->cfg_gpio = s3c_i2c0_cfg_gpio;//set GPIO as I2C func

	s3c_device_i2c0.dev.platform_data = npd;}//作私有变量


mach-mini2440.c //描述板子上的硬件设备信息

static struct i2c_board_info mini2440_i2c_devs[] __initdata = {
	{
		I2C_BOARD_INFO("24c08", 0x50), //type=24c08--device name
		.platform_data = &at24c08,	   //addr=0x50--device addr
	},
};
i2c_register_board_info(0, mini2440_i2c_devs,
				ARRAY_SIZE(mini2440_i2c_devs));//添加i2c外设	
。。。
platform_add_devices(&s3c_device_i2c0);
。。。



i2c-s3c2410.c


/* device driver for platform bus bits */

static struct platform_device_id s3c24xx_driver_ids[] = {
	{
		.name		= "s3c2410-i2c",
		.driver_data	= TYPE_S3C2410,
	}, {
		.name		= "s3c2440-i2c",
		.driver_data	= TYPE_S3C2440,
	}, { },
};

static struct platform_driver s3c24xx_i2c_driver = {
	.probe		= s3c24xx_i2c_probe,
	.remove		= s3c24xx_i2c_remove,
	.id_table	= s3c24xx_driver_ids,
	.driver		= {
		.owner	= THIS_MODULE,
		.name	= "s3c-i2c",
		.pm	= S3C24XX_DEV_PM_OPS,
	},
};








<pre name="code" class="cpp">/*platform_bus_type的match函数*/
static int platform_match(struct device *dev, struct device_driver *drv)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct platform_driver *pdrv = to_platform_driver(drv);

	/* match against the id table first */
	if (pdrv->id_table)
		return platform_match_id(pdrv->id_table, pdev) != NULL;

	/* fall-back to driver name match */
	return (strcmp(pdev->name, drv->name) == 0);
}

static const struct platform_device_id *platform_match_id(
			struct platform_device_id *id,
			struct platform_device *pdev)
{
	while (id->name[0]) {
                /*比较pdev设备名和驱动支持列表*/
		if (strcmp(pdev->name, id->name) == 0) {
			pdev->id_entry = id;
			return id;
		}
		id++;
	}
	return NULL;
}
由上面可以看出,设备名要在驱动支持列表里头才可以配对

/* s3c24xx_i2c_probe
 *
 * called by the bus driver when a suitable device is found
*/

static int s3c24xx_i2c_probe(struct platform_device *pdev)
{
    struct s3c24xx_i2c *i2c;
    struct s3c2410_platform_i2c *pdata;
    struct resource *res;
    int ret;
  /*取得私有变量--有时是获得指针,有时是获得变量,这里是获得已经初始化好的变量*/
    pdata = pdev->dev.platform_data;
    if (!pdata) {
        dev_err(&pdev->dev, "no platform data\n");
        return -EINVAL;
    }

    i2c = kzalloc(sizeof(struct s3c24xx_i2c), GFP_KERNEL);
    if (!i2c) {
        dev_err(&pdev->dev, "no memory for state\n");
        return -ENOMEM;
    }
  /*初始化adapter*/ 
    strlcpy(i2c->adap.name, "s3c2410-i2c", sizeof(i2c->adap.name));
    i2c->adap.owner   = THIS_MODULE;
    i2c->adap.algo    = &s3c24xx_i2c_algorithm;//通信方法,当有数据要传输时都会调用该函数
    i2c->adap.retries = 2;
    i2c->adap.class   = I2C_CLASS_HWMON | I2C_CLASS_SPD;
    i2c->tx_setup     = 50;

    spin_lock_init(&i2c->lock);
    init_waitqueue_head(&i2c->wait);

    /* find the clock and enable it */

    i2c->dev = &pdev->dev;
    i2c->clk = clk_get(&pdev->dev, "i2c");
    if (IS_ERR(i2c->clk)) {
        dev_err(&pdev->dev, "cannot get clock\n");
        ret = -ENOENT;
        goto err_noclk;
    }

    dev_dbg(&pdev->dev, "clock source %p\n", i2c->clk);

    clk_enable(i2c->clk);

    /* map the registers */

    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    if (res == NULL) {
        dev_err(&pdev->dev, "cannot find IO resource\n");
        ret = -ENOENT;
        goto err_clk;
    }

    i2c->ioarea = request_mem_region(res->start, resource_size(res),
                     pdev->name);

    if (i2c->ioarea == NULL) {
        dev_err(&pdev->dev, "cannot request IO\n");
        ret = -ENXIO;
        goto err_clk;
    }

    i2c->regs = ioremap(res->start, resource_size(res));

    if (i2c->regs == NULL) {
        dev_err(&pdev->dev, "cannot map IO\n");
        ret = -ENXIO;
        goto err_ioarea;
    }

    dev_dbg(&pdev->dev, "registers %p (%p, %p)\n",
        i2c->regs, i2c->ioarea, res);

    /* setup info block for the i2c core */

    i2c->adap.algo_data = i2c;
    i2c->adap.dev.parent = &pdev->dev;

    /* initialise the i2c controller */

    ret = s3c24xx_i2c_init(i2c);//初始化i2c频率
    if (ret != 0)
        goto err_iomap;

    /* find the IRQ for this unit (note, this relies on the init call to
     * ensure no current IRQs pending
     */

    i2c->irq = ret = platform_get_irq(pdev, 0);
    if (ret <= 0) {
        dev_err(&pdev->dev, "cannot find IRQ\n");
        goto err_iomap;
    }
    /*注册中断,每当发送或者接受一个完整的字节时就会进入中断*/
    ret = request_irq(i2c->irq, s3c24xx_i2c_irq, IRQF_DISABLED,
              dev_name(&pdev->dev), i2c);

    if (ret != 0) {
        dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq);
        goto err_iomap;
    }


    /* Note, previous versions of the driver used i2c_add_adapter()
     * to add the bus at any number. We now pass the bus number via
     * the platform data, so if unset it will now default to always
     * being bus 0.
     */

    i2c->adap.nr = pdata->bus_num;
  /*向系统添加i2c适配器*/ 
    ret = i2c_add_numbered_adapter(&i2c->adap);
    if (ret < 0) {
        dev_err(&pdev->dev, "failed to add bus to i2c core\n");
        goto err_cpufreq;
    }

    platform_set_drvdata(pdev, i2c);

    dev_info(&pdev->dev, "%s: S3C I2C adapter\n", dev_name(&i2c->adap.dev));
    return 0;

 err_cpufreq:
    s3c24xx_i2c_deregister_cpufreq(i2c);

 err_irq:
    free_irq(i2c->irq, i2c);

 err_iomap:
    iounmap(i2c->regs);

 err_ioarea:
    release_resource(i2c->ioarea);
    kfree(i2c->ioarea);

 err_clk:
    clk_disable(i2c->clk);
    clk_put(i2c->clk);

 err_noclk:
    kfree(i2c);
    return ret;
}

/* i2c bus registration info */

static const struct i2c_algorithm s3c24xx_i2c_algorithm = {
    .master_xfer        = s3c24xx_i2c_xfer,//通信方法
    .functionality        = s3c24xx_i2c_func,
};

/* s3c24xx_i2c_xfer
 *
 * first port of call from the i2c bus code when an message needs
 * transferring across the i2c bus.
*/

static int s3c24xx_i2c_xfer(struct i2c_adapter *adap,
            struct i2c_msg *msgs, int num)
{
    struct s3c24xx_i2c *i2c = (struct s3c24xx_i2c *)adap->algo_data;
    int retry;
    int ret;

    for (retry = 0; retry < adap->retries; retry++) {

        ret = s3c24xx_i2c_doxfer(i2c, msgs, num);//继续往下调用

        if (ret != -EAGAIN)
            return ret;

        dev_dbg(i2c->dev, "Retrying transmission (%d)\n", retry);

        udelay(100);
    }

    return -EREMOTEIO;
}

/* s3c24xx_i2c_doxfer
 *
 * this starts an i2c transfer
*/

static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
                  struct i2c_msg *msgs, int num)
{
    unsigned long timeout;
    unsigned long iicstat;
    int ret;

    if (i2c->suspended)
        return -EIO;

    ret = s3c24xx_i2c_set_master(i2c);
    if (ret != 0) {
        dev_err(i2c->dev, "cannot get bus (error %d)\n", ret);
        ret = -EAGAIN;
        goto out;
    }

    spin_lock_irq(&i2c->lock);
  //获取待传输的msg 
    i2c->msg     = msgs;//
    i2c->msg_num = num;
    i2c->msg_ptr = 0;
    i2c->msg_idx = 0;
    i2c->state   = STATE_START;

    s3c24xx_i2c_enable_irq(i2c);
    s3c24xx_i2c_message_start(i2c, msgs);//启动发送,发送address。当address传输完后,进入中断,在中断里判断是否传输错误
    spin_unlock_irq(&i2c->lock);

    timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 1);//等待超时或者传输完成。

    ret = i2c->msg_idx;

    /* having these next two as dev_err() makes life very
     * noisy when doing an i2cdetect */

    if (timeout == 0) {
        dev_dbg(i2c->dev, "timeout\n");
        iicstat = readl(i2c->regs + S3C2410_IICSTAT);

        /* stop the transfer */
        iicstat &= ~(S3C2410_IICSTAT_START | S3C2410_IICSTAT_TXRXEN);
        writel(iicstat, i2c->regs + S3C2410_IICSTAT);

        i2c->state = STATE_STOP;

        s3c24xx_i2c_master_complete(i2c, ret);
        s3c24xx_i2c_disable_irq(i2c);

        goto out;
    }
    else if (ret != num)
        dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret);

    /* ensure the stop has been through the bus */

    udelay(50);

 out:
    return ret;
}

/* s3c24xx_i2c_message_start
 *
 * put the start of a message onto the bus
*/

static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
                      struct i2c_msg *msg)
{
    unsigned int addr = (msg->addr & 0x7f) << 1;//获取address并左移一位,第8位表示读写
    unsigned long stat;
    unsigned long iiccon;

    stat = 0;
    stat |=  S3C2410_IICSTAT_TXRXEN;

    if (msg->flags & I2C_M_RD) {
        stat |= S3C2410_IICSTAT_MASTER_RX;
        addr |= 1;//赋值第8位
    } else
        stat |= S3C2410_IICSTAT_MASTER_TX;

    if (msg->flags & I2C_M_REV_DIR_ADDR)
        addr ^= 1;

    /* todo - check for wether ack wanted or not */
    s3c24xx_i2c_enable_ack(i2c);

    iiccon = readl(i2c->regs + S3C2410_IICCON);
    writel(stat, i2c->regs + S3C2410_IICSTAT);//启动传输

    dev_dbg(i2c->dev, "START: %08lx to IICSTAT, %02x to DS\n", stat, addr);
    writeb(addr, i2c->regs + S3C2410_IICDS);//将地址写到IICDS,通过SDA发送

    /* delay here to ensure the data byte has gotten onto the bus
     * before the transaction is started */

    ndelay(i2c->tx_setup);

    //dev_dbg(i2c->dev, "iiccon, %08lx\n", iiccon);
    //writel(iiccon, i2c->regs + S3C2410_IICCON);

    stat |= S3C2410_IICSTAT_START;
    writel(stat, i2c->regs + S3C2410_IICSTAT);
}
/*发送完一字节进中断*/
static irqreturn_t s3c24xx_i2c_irq(int irqno, void *dev_id)
{
    struct s3c24xx_i2c *i2c = dev_id;
    unsigned long status;
    unsigned long tmp;

    status = readl(i2c->regs + S3C2410_IICSTAT);//以下是判断是否传输有错误

    if (status & S3C2410_IICSTAT_ARBITR) {
        /* deal with arbitration loss */
        dev_err(i2c->dev, "deal with arbitration loss\n");
    }

    if (i2c->state == STATE_IDLE) {
        dev_dbg(i2c->dev, "IRQ: error i2c->state == IDLE\n");

        tmp = readl(i2c->regs + S3C2410_IICCON);
        tmp &= ~S3C2410_IICCON_IRQPEND;
        writel(tmp, i2c->regs +  S3C2410_IICCON);
        goto out;
    }

    /* pretty much this leaves us with the fact that we've
     * transmitted or received whatever byte we last sent */

    i2c_s3c_irq_nextbyte(i2c, status);//传送下一个字节

 out:
    return IRQ_HANDLED;
}

static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
{
    unsigned long tmp;
    unsigned char byte;
    int ret = 0;

    switch (i2c->state) {

    case STATE_IDLE:
        dev_err(i2c->dev, "%s: called in STATE_IDLE\n", __func__);
        goto out;
        break;

    case STATE_STOP:
        dev_err(i2c->dev, "%s: called in STATE_STOP\n", __func__);
        s3c24xx_i2c_disable_irq(i2c);
        goto out_ack;

    case STATE_START://标志为START有两种情况:1、刚开始,2、READ的重启时候
        /* last thing we did was send a start condition on the
         * bus, or started a new i2c message
         */

        if (iicstat & S3C2410_IICSTAT_LASTBIT &&
            !(i2c->msg->flags & I2C_M_IGNORE_NAK)) {
            /* ack was not received... */

            dev_dbg(i2c->dev, "ack was not received\n");
            s3c24xx_i2c_stop(i2c, -ENXIO);
            goto out_ack;
        }

        if (i2c->msg->flags & I2C_M_RD)
            i2c->state = STATE_READ;//READ的重启时候        
        else
            i2c->state = STATE_WRITE;//刚开始传输

        /* terminate the transfer if there is nothing to do
         * as this is used by the i2c probe to find devices. */

        if (is_lastmsg(i2c) && i2c->msg->len == 0) {
            s3c24xx_i2c_stop(i2c, 0);
            goto out_ack;
        }

        if (i2c->state == STATE_READ)//如果是READ,先要未读准备一下。如只读一个字节,如果是则要设置读完后主机不发送ACK等
            goto prepare_read;

        /* fall through to the write state, as we will need to
         * send a byte as well */

    case STATE_WRITE:
        /* we are writing data to the device... check for the
         * end of the message, and if so, work out what to do
         */

        if (!(i2c->msg->flags & I2C_M_IGNORE_NAK)) {
            if (iicstat & S3C2410_IICSTAT_LASTBIT) {
                dev_dbg(i2c->dev, "WRITE: No Ack\n");

                s3c24xx_i2c_stop(i2c, -ECONNREFUSED);
                goto out_ack;
            }
        }

 retry_write:

        if (!is_msgend(i2c)) {//msg是否传完数据
            byte = i2c->msg->buf[i2c->msg_ptr++];//指针自加1
            writeb(byte, i2c->regs + S3C2410_IICDS);//未传完数据,则要将数据写到CDS,通过SDA发送

            /* delay after writing the byte to allow the
             * data setup time on the bus, as writing the
             * data to the register causes the first bit
             * to appear on SDA, and SCL will change as
             * soon as the interrupt is acknowledged */

            ndelay(i2c->tx_setup);

        } else if (!is_lastmsg(i2c)) {//如果msg数据传完,且后面还有msg,则要跳到下一个msg
            /* we need to go to the next i2c message */

            dev_dbg(i2c->dev, "WRITE: Next Message\n");

            i2c->msg_ptr = 0;
            i2c->msg_idx++;
            i2c->msg++;//跳到下一个msg

            /* check to see if we need to do another message */
            if (i2c->msg->flags & I2C_M_NOSTART) {

                if (i2c->msg->flags & I2C_M_RD) {
                    /* cannot do this, the controller
                     * forces us to send a new START
                     * when we change direction */

                    s3c24xx_i2c_stop(i2c, -EINVAL);
                }

                goto retry_write;
            } else {
                /* send the new start */
                s3c24xx_i2c_message_start(i2c, i2c->msg);//这里是在case WRITE里,该msg数据传完(片内地址传完),且后面还有msg待传输,说明是主机要向从机读数据。因此重启I2C
                i2c->state = STATE_START;//设置I2C状态
            }

        } else {
            /* send stop */

            s3c24xx_i2c_stop(i2c, 0);
        }
        break;

    case STATE_READ:
        /* we have a byte of data in the data register, do
         * something with it, and then work out wether we are
         * going to do any more read/write
         */

        byte = readb(i2c->regs + S3C2410_IICDS);//(接受一个字节会进中断,且将值放在CDS里),获取数据
        i2c->msg->buf[i2c->msg_ptr++] = byte;//ptr指向下一个字节

 prepare_read:
        if (is_msglast(i2c)) {//仅剩最后一个字节未读取
            /* last byte of buffer */

            if (is_lastmsg(i2c))
                s3c24xx_i2c_disable_ack(i2c);//到时不发送ACK

        } 
     else if (is_msgend(i2c)) //数据接受完毕
     {
            /* ok, we've read the entire buffer, see if there
             * is anything else we need to do */

            if (is_lastmsg(i2c)) {//最后一个msg ?
                /* last message, send stop and complete */
                dev_dbg(i2c->dev, "READ: Send Stop\n");

                s3c24xx_i2c_stop(i2c, 0);//说明已经全部接受完毕,主机给从机发送停止信号
            } else {
                /* go to the next transfer */
                dev_dbg(i2c->dev, "READ: Next Transfer\n");

                i2c->msg_ptr = 0;
                i2c->msg_idx++;
                i2c->msg++;
            }
        }

        break;
    }

    /* acknowlegde the IRQ and get back on with the work */
//清中断,重新传输
 out_ack:
    tmp = readl(i2c->regs + S3C2410_IICCON);
    tmp &= ~S3C2410_IICCON_IRQPEND;
    writel(tmp, i2c->regs + S3C2410_IICCON);
 out:
    return ret;
}





 2、core

//除了添加adapter外还初始化并注册了挂接在这个adapter上的设备

int i2c_add_numbered_adapter(struct i2c_adapter *adap)
{//we have already set the adap->nr
	int	id;
	int	status;

	if (adap->nr & ~MAX_ID_MASK)
		return -EINVAL;

retry:
	if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0)
		return -ENOMEM;

	mutex_lock(&core_lock);
	/* "above" here means "above or equal to", sigh;
	 * we need the "equal to" result to force the result
	 */
	status = idr_get_new_above(&i2c_adapter_idr, adap, adap->nr, &id);//建立id与adap的关系

	if (status == 0 && id != adap->nr) {
		status = -EBUSY;
		idr_remove(&i2c_adapter_idr, id);
	}
	mutex_unlock(&core_lock);
	if (status == -EAGAIN)
		goto retry;

	if (status == 0)
		<span style="color:#ff0000;">status = i2c_register_adapter(adap);</span>
	return status;
}

static int i2c_register_adapter(struct i2c_adapter *adap)
{
	int res = 0;

	/* Can't register until after driver model init */
	if (unlikely(WARN_ON(!i2c_bus_type.p))) {
		res = -EAGAIN;
		goto out_list;
	}

	rt_mutex_init(&adap->bus_lock);
	mutex_init(&adap->userspace_clients_lock);
	INIT_LIST_HEAD(&adap->userspace_clients);

	/* Set default timeout to 1 second if not already set */
	if (adap->timeout == 0)
		adap->timeout = HZ;
												 //adap->dev.name=i2c0
	dev_set_name(&adap->dev, "i2c-%d", adap->nr);//i2c-0
	adap->dev.bus = &i2c_bus_type;
	adap->dev.type = &i2c_adapter_type;
	res = device_register(&adap->dev);//register adapter dev
	if (res)
		goto out_list;

	dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);

#ifdef CONFIG_I2C_COMPAT
	res = class_compat_create_link(i2c_adapter_compat_class, &adap->dev,
				       adap->dev.parent);
	if (res)
		dev_warn(&adap->dev,
			 "Failed to create compatibility class link\n");
#endif

	/* create pre-declared device nodes */
	if (adap->nr < __i2c_first_dynamic_bus_num)  //will call this
		<span style="color:#ff0000;"><strong>i2c_scan_static_board_info(adap);</strong></span>

	/* Notify drivers */
	mutex_lock(&core_lock);	//will not do this part
	bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter);
	mutex_unlock(&core_lock);

	return 0;

out_list:
	mutex_lock(&core_lock);
	idr_remove(&i2c_adapter_idr, adap->nr);
	mutex_unlock(&core_lock);
	return res;
}

static void i2c_scan_static_board_info(struct i2c_adapter *adapter)
{
	struct i2c_devinfo	*devinfo;

	down_read(&__i2c_board_lock);
	list_for_each_entry(devinfo, &__i2c_board_list, list) {
		if (devinfo->busnum == adapter->nr
			&& !i2c_new_device(adapter,
						&devinfo->board_info)) //initilize the device
			dev_err(&adapter->dev,
				"Can't create device at 0x%02x\n",
				devinfo->board_info.addr);
	}
	up_read(&__i2c_board_lock);
}

struct i2c_client *
i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
{
	struct i2c_client	*client;
	int			status;

	client = kzalloc(sizeof *client, GFP_KERNEL);
	if (!client)
		return NULL;

	client->adapter = adap;

	client->dev.platform_data = info->platform_data;

	if (info->archdata)
		client->dev.archdata = *info->archdata;

	client->flags = info->flags;
	client->addr = info->addr;
	client->irq = info->irq;

	strlcpy(client->name, info->type, sizeof(client->name));//set client name

	/* Check for address validity */
	status = i2c_check_client_addr_validity(client);
	if (status) {
		dev_err(&adap->dev, "Invalid %d-bit I2C address 0x%02hx\n",
			client->flags & I2C_CLIENT_TEN ? 10 : 7, client->addr);
		goto out_err_silent;
	}

	/* Check for address business */
	status = i2c_check_addr_busy(adap, client->addr);//check the addr occupied?
	if (status)
		goto out_err;

	client->dev.parent = &client->adapter->dev;//add on adapter
	client->dev.bus = &i2c_bus_type;
	client->dev.type = &i2c_client_type;
#ifdef CONFIG_OF
	client->dev.of_node = info->of_node;
#endif

	dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),
		     client->addr);//set clinet->dev.name=0-0x45
	status = device_register(&client->dev);//add the device first
	if (status)
		goto out_err;

	dev_dbg(&adap->dev, "client [%s] registered with bus id %s\n",
		client->name, dev_name(&client->dev));

	return client;

out_err:
	dev_err(&adap->dev, "Failed to register i2c client %s at 0x%02x "
		"(%d)\n", client->name, client->addr, status);
out_err_silent:
	kfree(client);
	return NULL;
}
int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
{
	unsigned long orig_jiffies;
	int ret, try;
	if (adap->algo->master_xfer) {
#ifdef DEBUG
		for (ret = 0; ret < num; ret++) {
			dev_dbg(&adap->dev, "master_xfer[%d] %c, addr=0x%02x, "
				"len=%d%s\n", ret, (msgs[ret].flags & I2C_M_RD)
				? 'R' : 'W', msgs[ret].addr, msgs[ret].len,
				(msgs[ret].flags & I2C_M_RECV_LEN) ? "+" : "");
		}
#endif

		if (in_atomic() || irqs_disabled()) {
			ret = i2c_trylock_adapter(adap);
			if (!ret)
				/* I2C activity is ongoing. */
				return -EAGAIN;
		} else {
			i2c_lock_adapter(adap);
		}/* Retry automatically on arbitration loss */
orig_jiffies = jiffies;
for (ret = 0, try = 0; try <= adap->retries; try++) {
ret = adap->algo->master_xfer(adap, msgs, num);//transfer msg--见上面
if (ret != -EAGAIN)
break;
if (time_after(jiffies, orig_jiffies + adap->timeout))
break;
}
i2c_unlock_adapter(adap);
return ret;
} else {
dev_dbg(&adap->dev, "I2C level transfers not supported\n");
return -EOPNOTSUPP;
}
}







   

你可能感兴趣的:(linux I2C二)