【正文】
s3c24xx_i2c_disable_ack(i2c)。 //最后一個(gè)消息if (is_lastmsg(i2c)) //一個(gè)消息的最后一個(gè)字節(jié)if (is_msglast(i2c)) { prepare_read:i2cmsgbuf[i2cmsg_ptr++] = byte。 //從數(shù)據(jù)寄存器讀出數(shù)據(jù) case STATE_READ:break。 } //所有消息傳遞結(jié)束,停止總線s3c24xx_i2c_stop(i2c, 0)。 } else { } i2cstate = STATE_START。 s3c24xx_i2c_message_start(i2c, i2cmsg)。 /* send the new start */ //開(kāi)始傳輸消息,將IICDS的數(shù)據(jù)發(fā)到總線上} else { goto retry_write。 } * when we change direction */ /* cannot do this, the controller if (i2cmsgflags amp。 //不處理這種新類(lèi)型的消息,直接停止if (i2cmsgflags amp。 /* we need to go to the next i2c message */ * soon as the interrupt is acknowledged */ * data to the register causes the first bit /* delay after writing the byte to allow the //讀出緩沖區(qū)中的數(shù)據(jù),并增加偏移 if (!is_msgend(i2c)) { retry_write: 判斷一個(gè)消息是否結(jié)束,如果沒(méi)有,則執(zhí)行下面的分支 s3c24xx_i2c_stop(i2c, ECONNREFUSED)。 S3C2410_IICSTAT_LASTBIT) { //沒(méi)有接收到IIC設(shè)備的ACK信號(hào),表示出錯(cuò),停止總線傳輸if (!(i2cmsgflags amp。 */ * end of the message, and if so, work out what to do /* we are writing data to the device... check for the case STATE_WRITE: goto prepare_read。 goto out_ack。 s3c24xx_i2c_stop(i2c, 0)。 //is_lastmsg()判斷是否只有一條消息,如果這條消息為0字節(jié),那么發(fā)送停止信號(hào)P。amp。 i2cstate = STATE_WRITE。 i2cstate = STATE_READ。 I2C_M_RD) goto out_ack。 s3c24xx_i2c_stop(i2c, ENXIO)。 dev_dbg(i2cdev, ack was not received\n)。 //當(dāng)沒(méi)有接收到IIC設(shè)備的應(yīng)答ACK信號(hào),說(shuō)明對(duì)應(yīng)地址的IIC設(shè)備不存在,停止總線工作 !(i2cmsgflags amp。 amp。if (iicstat amp。 */ * bus, or started a new i2c message /* last thing we did was send a start condition on the //發(fā)出開(kāi)始信號(hào)S dev_err(i2cdev, %s: called in STATE_STOP\n, __func__)。 這是即使有數(shù)據(jù)產(chǎn)生,也不會(huì)產(chǎn)生中斷信號(hào) goto out。 //寄存器緩存 //寄存器緩存unsigned long tmp。return IRQ_HANDLED。 //傳輸或者接收下一個(gè)字節(jié)i2s_s3c_irq_nextbyte(i2c, status)。 ve }goto out。 //寫(xiě)IICCON寄存器writel(tmp, i2cregs + //將 IICCON的位[4]清零,表示清除中斷tmp amp。 //讀IICCON寄存器 dev_dbg(i2cdev, IRQ: error i2cstate == IDLE\n)。 要使繼續(xù)傳輸數(shù)據(jù),需要寫(xiě)入0清除這種中斷一般由總線仲裁引起,不會(huì)涉及數(shù)據(jù)的發(fā)送,所以清除中斷標(biāo)志后,直接跳出。 }dev_err(i2cdev, deal with arbitration loss\n)。 /* deal with arbitration loss */ //因仲裁失敗引發(fā)的中斷,IICSTAT[3]為0,表示仲裁成功,為1,表示失敗 S3C2410_IICSTAT_ARBITR) { //讀取IICSTAT的值 //緩存寄存器 //緩存IICSTATunsigned long status。struct s3c24xx_i2c *i2c = dev_id。這步由s3c24xx_i2c_set_master()和s3c24xx_i2c_message_start()完成。通過(guò)s3c24xx_i2c_algorithm通信方法中函數(shù)的調(diào)用關(guān)系,數(shù)據(jù)通信的過(guò)程如下:1,傳輸數(shù)據(jù)時(shí),調(diào)用s3c24xx_i2c_algorithm結(jié)構(gòu)體中的數(shù)據(jù)傳輸函數(shù)s3c24xx_i2c_xfer()2,s3c24xx_i2c_xfer()中會(huì)調(diào)用s3c24xx_i2c_doxfer()進(jìn)行數(shù)據(jù)的傳輸3,s3c24xx_i2c_doxfer()中向總線 發(fā)送IIC設(shè)備地址和開(kāi)始信號(hào)S后,便會(huì)調(diào)用wati_event_timeout()函數(shù)進(jìn)入等待狀態(tài)4,將數(shù)據(jù)準(zhǔn)備好發(fā)送時(shí),將產(chǎn)生中斷,并調(diào)用實(shí)現(xiàn)注冊(cè)的中斷處理函數(shù)s3c24xx_i2c_irq()5,s3c24xx_i2c_irq()調(diào)用下一個(gè)字節(jié)傳輸函數(shù)i2s_s3c_irq_nextbyte()來(lái)傳輸數(shù)據(jù)6,當(dāng)數(shù)據(jù)傳輸完成后,會(huì)調(diào)用 s3c24xx_i2c_stop().7,最后調(diào)用wake_up()喚醒等待隊(duì)列,完成數(shù)據(jù)的傳輸過(guò)程傳輸數(shù)據(jù)的過(guò)程被交到了中斷處理函數(shù)中。 //取出IICCON寄存器的值 //暫存IICCON寄存器 //使能ACK響應(yīng)信號(hào){ //設(shè)置為啟動(dòng)狀態(tài)stat |= S3C2410_IICSTAT_START。 //延時(shí),以使數(shù)據(jù)寫(xiě)入寄存器中 * before the transaction is started */ 將IIC設(shè)備地址寫(xiě)入IICDS寄存器中,寄存器值[7:1]表示設(shè)備地址。 //打印調(diào)試信息dev_dbg(i2cdev, START: %08lx to IICSTAT, %02x to DS\n, stat, addr)。 //讀出IICCON寄存器的值iiccon = readl(i2cregs + S3C2410_IICCON)。s3c24xx_i2c_enable_ack(i2c)。 I2C_M_REV_DIR_ADDR) //將適配器設(shè)置為主機(jī)發(fā)送器 } else stat |= S3C2410_IICSTAT_MASTER_RX。 //如果消息類(lèi)型是從IIC設(shè)備到適配器讀數(shù)據(jù)if (msgflags amp。 S3C2410_IICSTAT_TXRXEN。 //狀態(tài)初始化為0 //緩存IICCO寄存器unsigned long iiccon。unsigned long stat。 //取從設(shè)備的低7位地址,并向前移動(dòng)一位。unsigned int addr = (msgaddr amp。 主要功能:1,s3c2440的適配器對(duì)應(yīng)的IICON和IICSTAT寄存器2,寫(xiě)從設(shè)備地址,并發(fā)出開(kāi)始信號(hào)Sstatic void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c, //將IICCON的第5位置1}writel(tmp | S3C2410_IICCON_IRQEN, i2cregs + S3C2410_IICCON)。tmp = readl(i2cregs + S3C2410_IICCON)。unsigned long tmp。s3c24xx_i2c_enable_irq()函數(shù)用來(lái)使中斷使能。當(dāng)數(shù)據(jù)發(fā)送完后,會(huì)從總線發(fā)送一個(gè)中斷信號(hào),喚醒睡眠中的進(jìn)程,所以適配器應(yīng)該使能中斷。} }msleep(1)。 //檢查第5位是否為0 S3C2410_IICSTAT_BUSBUSY)) //嘗試400次,獲得總線 //用于存儲(chǔ)IICSTAT的狀態(tài) 當(dāng)為0時(shí),總線空閑;當(dāng)為1時(shí)總線繁忙:static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c){判斷總線閑忙狀態(tài)s3c24xx_i2c_set_master():在適配器發(fā)送數(shù)據(jù)以前,需要判斷總線的忙閑狀態(tài)。 //總線停止?fàn)顟B(tài)}。STATE_STOPSTATE_WRITE,STATE_READ,STATE_START,STATE_IDLE,} out: /* ensure the stop has been through the bus */dev_dbg(i2cdev, inplete xfer (%d)\n, ret)。 //未寫(xiě)完規(guī)定的消息個(gè)數(shù),則失敗else if (ret != num)dev_dbg(i2cdev, timeout\n)。 //在規(guī)定的時(shí)間內(nèi),沒(méi)有成功的寫(xiě)入數(shù)據(jù) * noisy when doing an i2cdetect */ spin_unlock_irq(amp。注意一次i2c操作可能要涉及多個(gè)字節(jié),只有第一個(gè)字節(jié)發(fā)送是在當(dāng)前進(jìn)程的文件系統(tǒng)操作執(zhí)行流中進(jìn)行的,該字節(jié)操作的完成及后繼字節(jié)的寫(xiě)入都由中斷處理程序來(lái)完成。s3c