/* * I2C adapter for the ASPEED I2C bus access. * * Copyright (C) 2012-2020 ASPEED Technology Inc. * Copyright 2015 IBM Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * History: * 2012.07.26: Initial version [Ryan Chen] */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(CONFIG_COLDFIRE) #include #include #else //#include //#include #endif #define BYTE_MODE 0 #define BUFF_MODE 1 #define DEC_DMA_MODE 2 #define INC_DMA_MODE 3 /* I2C Register */ #define I2C_FUN_CTRL_REG 0x00 #define I2C_AC_TIMING_REG1 0x04 #define I2C_AC_TIMING_REG2 0x08 #define I2C_INTR_CTRL_REG 0x0c #define I2C_INTR_STS_REG 0x10 #define I2C_CMD_REG 0x14 #define I2C_DEV_ADDR_REG 0x18 #define I2C_BUF_CTRL_REG 0x1c #define I2C_BYTE_BUF_REG 0x20 #define I2C_DMA_BASE_REG 0x24 #define I2C_DMA_LEN_REG 0x28 #define AST_I2C_DMA_SIZE 0 #define AST_I2C_PAGE_SIZE 256 #define MASTER_XFER_MODE BUFF_MODE #define SLAVE_XFER_MODE BYTE_MODE #define NUM_BUS 14 /*AST I2C Register Definition */ // if defined(AST_SOC_G4) #define AST_I2C_POOL_BUFF_2048 #define AST_I2C_GLOBAL_REG 0x00 #define AST_I2C_DEVICE1 0x40 #define AST_I2C_DEVICE2 0x80 #define AST_I2C_DEVICE3 0xc0 #define AST_I2C_DEVICE4 0x100 #define AST_I2C_DEVICE5 0x140 #define AST_I2C_DEVICE6 0x180 #define AST_I2C_DEVICE7 0x1c0 #define AST_I2C_BUFFER_POOL2 0x200 #define AST_I2C_DEVICE8 0x300 #define AST_I2C_DEVICE9 0x340 #define AST_I2C_DEVICE10 0x380 #define AST_I2C_DEVICE11 0x3c0 #define AST_I2C_DEVICE12 0x400 #define AST_I2C_DEVICE13 0x440 #define AST_I2C_DEVICE14 0x480 #define AST_I2C_BUFFER_POOL1 0x800 /* Gloable Register Definition */ /* 0x00 : I2C Interrupt Status Register */ /* 0x08 : I2C Interrupt Target Assignment */ /* Device Register Definition */ /* 0x00 : I2CD Function Control Register */ #define AST_I2CD_BUFF_SEL_MASK (0x7 << 20) #define AST_I2CD_BUFF_SEL(x) (x << 20) // page 0 ~ 7 #define AST_I2CD_M_SDA_LOCK_EN (0x1 << 16) #define AST_I2CD_MULTI_MASTER_DIS (0x1 << 15) #define AST_I2CD_M_SCL_DRIVE_EN (0x1 << 14) #define AST_I2CD_MSB_STS (0x1 << 9) #define AST_I2CD_SDA_DRIVE_1T_EN (0x1 << 8) #define AST_I2CD_M_SDA_DRIVE_1T_EN (0x1 << 7) #define AST_I2CD_M_HIGH_SPEED_EN (0x1 << 6) #define AST_I2CD_DEF_ADDR_EN (0x1 << 5) #define AST_I2CD_DEF_ALERT_EN (0x1 << 4) #define AST_I2CD_DEF_ARP_EN (0x1 << 3) #define AST_I2CD_DEF_GCALL_EN (0x1 << 2) #define AST_I2CD_SLAVE_EN (0x1 << 1) #define AST_I2CD_MASTER_EN (0x1 ) /* 0x04 : I2CD Clock and AC Timing Control Register #1 */ #define AST_I2CD_tBUF (0x1 << 28) // 0~7 #define AST_I2CD_tHDSTA (0x1 << 24) // 0~7 #define AST_I2CD_tACST (0x1 << 20) // 0~7 #define AST_I2CD_tCKHIGH (0x1 << 16) // 0~7 #define AST_I2CD_tCKLOW (0x1 << 12) // 0~7 #define AST_I2CD_tHDDAT (0x1 << 10) // 0~7 #define AST_I2CD_CLK_TO_BASE_DIV (0x1 << 8) // 0~3 #define AST_I2CD_CLK_BASE_DIV (0x1 ) // 0~0xf /* 0x08 : I2CD Clock and AC Timing Control Register #2 */ #define AST_I2CD_tTIMEOUT (0x1 ) // 0~7 #define AST_NO_TIMEOUT_CTRL 0x0 /* 0x0c : I2CD Interrupt Control Register */ #define AST_I2CD_SDA_DL_TO_INTR_EN (0x1 << 14) #define AST_I2CD_BUS_RECOVER_INTR_EN (0x1 << 13) #define AST_I2CD_SMBUS_ALT_INTR_EN (0x1 << 12) #define AST_I2CD_SLAVE_MATCH_INTR_EN (0x1 << 7) #define AST_I2CD_SCL_TO_INTR_EN (0x1 << 6) #define AST_I2CD_ABNORMAL_INTR_EN (0x1 << 5) #define AST_I2CD_NORMAL_STOP_INTR_EN (0x1 << 4) #define AST_I2CD_ARBIT_LOSS_INTR_EN (0x1 << 3) #define AST_I2CD_RX_DOWN_INTR_EN (0x1 << 2) #define AST_I2CD_TX_NAK_INTR_EN (0x1 << 1) #define AST_I2CD_TX_ACK_INTR_EN (0x1 ) /* 0x10 : I2CD Interrupt Status Register : WC */ #define AST_I2CD_INTR_STS_SDA_DL_TO (0x1 << 14) #define AST_I2CD_INTR_STS_BUS_RECOVER (0x1 << 13) #define AST_I2CD_INTR_STS_SMBUS_ALT (0x1 << 12) #define AST_I2CD_INTR_STS_SMBUS_ARP_ADDR (0x1 << 11) #define AST_I2CD_INTR_STS_SMBUS_DEV_ALT (0x1 << 10) #define AST_I2CD_INTR_STS_SMBUS_DEF_ADDR (0x1 << 9) #define AST_I2CD_INTR_STS_GCALL_ADDR (0x1 << 8) #define AST_I2CD_INTR_STS_SLAVE_MATCH (0x1 << 7) #define AST_I2CD_INTR_STS_SCL_TO (0x1 << 6) #define AST_I2CD_INTR_STS_ABNORMAL (0x1 << 5) #define AST_I2CD_INTR_STS_NORMAL_STOP (0x1 << 4) #define AST_I2CD_INTR_STS_ARBIT_LOSS (0x1 << 3) #define AST_I2CD_INTR_STS_RX_DOWN (0x1 << 2) #define AST_I2CD_INTR_STS_TX_NAK (0x1 << 1) #define AST_I2CD_INTR_STS_TX_ACK (0x1 ) /* 0x14 : I2CD Command/Status Register */ #define AST_I2CD_SDA_OE (0x1 << 28) #define AST_I2CD_SDA_O (0x1 << 27) #define AST_I2CD_SCL_OE (0x1 << 26) #define AST_I2CD_SCL_O (0x1 << 25) #define AST_I2CD_TX_TIMING (0x1 << 24) // 0 ~3 #define AST_I2CD_TX_STATUS (0x1 << 23) // Tx State Machine #define AST_I2CD_IDLE 0x0 #define AST_I2CD_MACTIVE 0x8 #define AST_I2CD_MSTART 0x9 #define AST_I2CD_MSTARTR 0xa #define AST_I2CD_MSTOP 0xb #define AST_I2CD_MTXD 0xc #define AST_I2CD_MRXACK 0xd #define AST_I2CD_MRXD 0xe #define AST_I2CD_MTXACK 0xf #define AST_I2CD_SWAIT 0x1 #define AST_I2CD_SRXD 0x4 #define AST_I2CD_STXACK 0x5 #define AST_I2CD_STXD 0x6 #define AST_I2CD_SRXACK 0x7 #define AST_I2CD_RECOVER 0x3 #define AST_I2CD_SCL_LINE_STS (0x1 << 18) #define AST_I2CD_SDA_LINE_STS (0x1 << 17) #define AST_I2CD_BUS_BUSY_STS (0x1 << 16) #define AST_I2CD_SDA_OE_OUT_DIR (0x1 << 15) #define AST_I2CD_SDA_O_OUT_DIR (0x1 << 14) #define AST_I2CD_SCL_OE_OUT_DIR (0x1 << 13) #define AST_I2CD_SCL_O_OUT_DIR (0x1 << 12) #define AST_I2CD_BUS_RECOVER_CMD_EN (0x1 << 11) #define AST_I2CD_S_ALT_EN (0x1 << 10) // 0 : DMA Buffer, 1: Pool Buffer //AST1070 DMA register #define AST_I2CD_RX_DMA_ENABLE (0x1 << 9) #define AST_I2CD_TX_DMA_ENABLE (0x1 << 8) /* Command Bit */ #define AST_I2CD_RX_BUFF_ENABLE (0x1 << 7) #define AST_I2CD_TX_BUFF_ENABLE (0x1 << 6) #define AST_I2CD_M_STOP_CMD (0x1 << 5) #define AST_I2CD_M_S_RX_CMD_LAST (0x1 << 4) #define AST_I2CD_M_RX_CMD (0x1 << 3) #define AST_I2CD_S_TX_CMD (0x1 << 2) #define AST_I2CD_M_TX_CMD (0x1 << 1) #define AST_I2CD_M_START_CMD (0x1 ) /* 0x18 : I2CD Slave Device Address Register */ /* 0x1C : I2CD Pool Buffer Control Register */ #define AST_I2CD_RX_BUF_ADDR_GET(x) ((x>> 24)& 0xff) #define AST_I2CD_RX_BUF_END_ADDR_SET(x) (x << 16) #define AST_I2CD_TX_DATA_BUF_END_SET(x) ((x&0xff) << 8) #define AST_I2CD_TX_DATA_BUF_GET(x) ((x >>8) & 0xff) #define AST_I2CD_BUF_BASE_ADDR_SET(x) (x & 0x3f) /* 0x20 : I2CD Transmit/Receive Byte Buffer Register */ #define AST_I2CD_GET_MODE(x) ((x >> 8) & 0x1) #define AST_I2CD_RX_BYTE_BUFFER (0xff << 8) #define AST_I2CD_TX_BYTE_BUFFER (0xff ) //I2C MEMORY Device state machine typedef enum i2c_slave_stage { INIT_STAGE, CMD_STAGE, CMD_DATA_STAGE, DATA_STAGE } stage; typedef enum i2c_xfer_mode { BYTE_XFER, BUFF_XFER, DEC_DMA_XFER, INC_DMA_XFER } i2c_xfer_mode_t; //1. usage flag , 2 size, 3. request address struct buf_page { u8 flag; //0:free to usage, 1: used u8 page_no; //for AST2400 usage u16 page_size; u32 page_addr; u32 page_addr_point; }; typedef enum i2c_slave_event_e { I2C_SLAVE_EVENT_START_READ, I2C_SLAVE_EVENT_READ, I2C_SLAVE_EVENT_START_WRITE, I2C_SLAVE_EVENT_WRITE, I2C_SLAVE_EVENT_NACK, I2C_SLAVE_EVENT_STOP } i2c_slave_event_t; //AST2400 buffer mode issue , force I2C slave write use byte mode , read use buffer mode /* Use platform_data instead of module parameters */ /* Fast Mode = 400 kHz, Standard = 100 kHz */ //static int clock = 100; /* Default: 100 kHz */ struct aspeed_i2c_bus { /* TODO: find a better way to do this */ struct ast_i2c_dev *i2c_dev; struct device *dev; void __iomem *base; /* virtual */ u32 bus_id; //for i2c dev# IRQ number check u32 state; //I2C xfer mode state matchine struct i2c_adapter adap; struct buf_page *req_page; //master dma or buff mode needed unsigned char *dma_buf; dma_addr_t dma_addr; u32 bus_clk; void (*slave_xfer)(i2c_slave_event_t event, struct i2c_msg **msgs); void (*slave_init)(struct i2c_msg **msgs); /* Master */ int xfer_last; //cur xfer is last msgs for stop msgs struct i2c_msg *master_msgs; //cur xfer msgs int master_xfer_len; //cur xfer len int master_xfer_cnt; //total xfer count u32 master_xfer_mode; //cur xfer mode ... 0 : no_op , master: 1 byte , 2 : buffer , 3: dma , slave : xxxx struct completion cmd_complete; int cmd_err; u8 blk_r_flag; //for smbus block read void (*do_master_xfer)(struct aspeed_i2c_bus *i2c_bus); void (*do_master_xfer_done)(struct aspeed_i2c_bus *i2c_bus); /* Slave */ u8 slave_operation; u8 slave_event; struct i2c_msg *slave_msgs; int slave_xfer_len; int slave_xfer_cnt; u32 slave_xfer_mode; void (*do_slave_xfer)(struct aspeed_i2c_bus *bus); void (*do_slave_xfer_done)(struct aspeed_i2c_bus *bus); }; struct ast_i2c_dev { struct device *dev; void __iomem *reg_gr; struct clk *pclk; struct aspeed_i2c_bus buses[14]; int irq; //I2C IRQ number }; #ifdef CONFIG_AST_I2C_SLAVE_RDWR #define I2C_S_BUF_SIZE 64 #define I2C_S_RX_BUF_NUM 4 #define BUFF_FULL 0xff00 #define BUFF_ONGOING 1 struct i2c_msg slave_rx_msg[I2C_S_RX_BUF_NUM + 1]; struct i2c_msg slave_tx_msg; #endif static inline void ast_i2c_write(struct aspeed_i2c_bus *bus, u32 val, u32 reg) { writel(val, bus->base + reg); } static inline u32 ast_i2c_read(struct aspeed_i2c_bus *bus, u32 reg) { return readl(bus->base + reg); } static u32 select_i2c_clock(struct aspeed_i2c_bus *bus) { unsigned int inc = 0, div, divider_ratio; u32 SCL_Low, SCL_High, data; divider_ratio = clk_get_rate(bus->i2c_dev->pclk) / bus->bus_clk; for (div = 0; divider_ratio >= 16; div++) { inc |= (divider_ratio & 1); divider_ratio >>= 1; } divider_ratio += inc; SCL_Low = (divider_ratio >> 1) - 1; SCL_High = divider_ratio - SCL_Low - 2; data = 0x77700300 | (SCL_High << 16) | (SCL_Low << 12) | div; return data; } #ifdef CONFIG_AST_I2C_SLAVE_MODE /* AST I2C Slave mode */ static void ast_slave_issue_alert(struct aspeed_i2c_bus *bus, u8 enable) { //only support dev0~3 if(bus->bus_id > 3) return; else { if(enable) ast_i2c_write(bus, ast_i2c_read(bus, I2C_CMD_REG) | AST_I2CD_S_ALT_EN, I2C_CMD_REG); else ast_i2c_write(bus, ast_i2c_read(bus, I2C_CMD_REG) & ~AST_I2CD_S_ALT_EN, I2C_CMD_REG); } } static void ast_slave_mode_enable(struct aspeed_i2c_bus *bus, struct i2c_msg *msgs) { if (msgs->buf[0] == 1) { ast_i2c_write(bus, msgs->addr, I2C_DEV_ADDR_REG); ast_i2c_write(bus, ast_i2c_read(bus, I2C_FUN_CTRL_REG) | AST_I2CD_SLAVE_EN, I2C_FUN_CTRL_REG); } else ast_i2c_write(bus, ast_i2c_read(bus, I2C_FUN_CTRL_REG) & ~AST_I2CD_SLAVE_EN, I2C_FUN_CTRL_REG); } #endif static void ast_i2c_dev_init(struct aspeed_i2c_bus *bus) { //I2CG Reset ast_i2c_write(bus, 0, I2C_FUN_CTRL_REG); #ifdef CONFIG_AST_I2C_SLAVE_EEPROM bus->slave_init(&(bus->slave_msgs)); ast_slave_mode_enable(bus, bus->slave_msgs); #endif //Enable Master Mode ast_i2c_write(bus, ast_i2c_read(bus, I2C_FUN_CTRL_REG) | AST_I2CD_MASTER_EN, I2C_FUN_CTRL_REG); /* Set AC Timing */ if(bus->bus_clk / 1000 > 400) { ast_i2c_write(bus, ast_i2c_read(bus, I2C_FUN_CTRL_REG) | AST_I2CD_M_HIGH_SPEED_EN | AST_I2CD_M_SDA_DRIVE_1T_EN | AST_I2CD_SDA_DRIVE_1T_EN, I2C_FUN_CTRL_REG); /* Set AC Timing */ ast_i2c_write(bus, 0x3, I2C_AC_TIMING_REG2); ast_i2c_write(bus, select_i2c_clock(bus), I2C_AC_TIMING_REG1); } else { /* target apeed is xxKhz*/ ast_i2c_write(bus, select_i2c_clock(bus), I2C_AC_TIMING_REG1); ast_i2c_write(bus, AST_NO_TIMEOUT_CTRL, I2C_AC_TIMING_REG2); } // ast_i2c_write(i2c_dev, 0x77743335, I2C_AC_TIMING_REG1); //Clear Interrupt ast_i2c_write(bus, 0xfffffff, I2C_INTR_STS_REG); //TODO // ast_i2c_write(i2c_dev, 0xAF, I2C_INTR_CTRL_REG); //Enable Interrupt, STOP Interrupt has bug in AST2000 /* Set interrupt generation of I2C controller */ ast_i2c_write(bus, AST_I2CD_SDA_DL_TO_INTR_EN | AST_I2CD_BUS_RECOVER_INTR_EN | AST_I2CD_SMBUS_ALT_INTR_EN | // AST_I2CD_SLAVE_MATCH_INTR_EN | AST_I2CD_SCL_TO_INTR_EN | AST_I2CD_ABNORMAL_INTR_EN | AST_I2CD_NORMAL_STOP_INTR_EN | AST_I2CD_ARBIT_LOSS_INTR_EN | AST_I2CD_RX_DOWN_INTR_EN | AST_I2CD_TX_NAK_INTR_EN | AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); } #ifdef CONFIG_AST_I2C_SLAVE_RDWR //for memory buffer initial static void ast_i2c_slave_buff_init(struct ast_i2c_dev *i2c_dev) { int i; //Tx buf 1 slave_tx_msg.len = I2C_S_BUF_SIZE; slave_tx_msg.buf = kzalloc(I2C_S_BUF_SIZE, GFP_KERNEL); //Rx buf 4 for(i=0; islave_event) { case I2C_SLAVE_EVENT_START_WRITE: for(i=0; idev,"RX buffer full ........use tmp msgs buff \n"); //TODO... } dev_dbg(bus->dev,"I2C_SLAVE_EVENT_START_WRITE ... %d \n", i); i2c_dev->slave_msgs = &slave_rx_msg[i]; break; case I2C_SLAVE_EVENT_START_READ: dev_dbg(bus->dev,"I2C_SLAVE_EVENT_START_READ ERROR .. not imple \n"); i2c_dev->slave_msgs = &slave_tx_msg; break; case I2C_SLAVE_EVENT_WRITE: dev_dbg(bus->dev,"I2C_SLAVE_EVENT_WRITE next write ERROR ...\n"); i2c_dev->slave_msgs = &slave_tx_msg; break; case I2C_SLAVE_EVENT_READ: dev_dbg(bus->dev,"I2C_SLAVE_EVENT_READ ERROR ... \n"); i2c_dev->slave_msgs = &slave_tx_msg; break; case I2C_SLAVE_EVENT_NACK: dev_dbg(bus->dev,"I2C_SLAVE_EVENT_NACK ERROR ... \n"); i2c_dev->slave_msgs = &slave_tx_msg; break; case I2C_SLAVE_EVENT_STOP: dev_dbg(bus->dev,"I2C_SLAVE_EVENT_STOP \n"); for(i=0; islave_msgs = &slave_tx_msg; break; } spin_unlock(&lock); } static int ast_i2c_slave_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs) { struct aspeed_i2c_bus *bus = adap->algo_data; int ret = 0, i; switch(msgs->flags) { case 0: dev_dbg(bus->dev, "slave read \n"); //cur_msg = get_free_msg; for (i = 0; i < I2C_S_RX_BUF_NUM; i++) { if ((slave_rx_msg[i].addr == 0) && (slave_rx_msg[i].flags == BUFF_FULL)) { memcpy(msgs->buf, slave_rx_msg[i].buf, slave_rx_msg[i].len); msgs->len = slave_rx_msg[i].len; slave_rx_msg[i].flags = 0; slave_rx_msg[i].len = 0; break; } } if (i == I2C_S_RX_BUF_NUM) { dev_dbg(bus->dev, "No buffer ........ \n"); msgs->len = 0; ret = -1; } break; case I2C_M_RD: //slave write dev_dbg(bus->dev, "slave write \n"); memcpy(msgs->buf, slave_tx_msg.buf, I2C_S_BUF_SIZE); break; case I2C_S_EN: if((msgs->addr < 0x1) || (msgs->addr > 0xff)) { ret = -1; dev_dbg(bus->dev,"addrsss not correct !! \n"); return ret; } if (msgs->len != 1) dev_dbg(bus->dev,"ERROR \n"); ast_slave_mode_enable(bus, msgs); break; case I2C_S_ALT: dev_dbg(bus->dev, "slave issue alt\n"); if (msgs->len != 1) dev_dbg(bus->dev,"ERROR \n"); if (msgs->buf[0] == 1) ast_slave_issue_alert(bus, 1); else ast_slave_issue_alert(bus, 0); break; default: dev_err(bus->dev, "slave xfer error \n"); break; } return ret; } #endif static u8 ast_i2c_bus_error_recover(struct aspeed_i2c_bus *bus) { u32 sts; int r; u32 i = 0; //Check 0x14's SDA and SCL status sts = ast_i2c_read(bus,I2C_CMD_REG); if ((sts & AST_I2CD_SDA_LINE_STS) && (sts & AST_I2CD_SCL_LINE_STS)) { //Means bus is idle. dev_dbg(bus->dev, "I2C bus (%d) is idle. I2C slave doesn't exist?!\n", bus->bus_id); return -1; } dev_dbg(bus->dev, "ERROR!! I2C(%d) bus hanged, try to recovery it!\n", bus->bus_id); if ((sts & AST_I2CD_SDA_LINE_STS) && !(sts & AST_I2CD_SCL_LINE_STS)) { //if SDA == 1 and SCL == 0, it means the master is locking the bus. //Send a stop command to unlock the bus. dev_dbg(bus->dev, "I2C's master is locking the bus, try to stop it.\n"); init_completion(&bus->cmd_complete); ast_i2c_write(bus, AST_I2CD_M_STOP_CMD, I2C_CMD_REG); r = wait_for_completion_interruptible_timeout(&bus->cmd_complete, bus->adap.timeout*HZ); if (bus->cmd_err) { dev_dbg(bus->dev, "recovery error \n"); return -1; } if (r == 0) { dev_dbg(bus->dev, "recovery timed out\n"); return -1; } else { dev_dbg(bus->dev, "Recovery successfully\n"); return 0; } } else if (!(sts & AST_I2CD_SDA_LINE_STS)) { //else if SDA == 0, the device is dead. We need to reset the bus //And do the recovery command. dev_dbg(bus->dev, "I2C's slave is dead, try to recover it\n"); //Let's retry 10 times for (i = 0; i < 10; i++) { ast_i2c_dev_init(bus); //Do the recovery command BIT11 init_completion(&bus->cmd_complete); ast_i2c_write(bus, AST_I2CD_BUS_RECOVER_CMD_EN, I2C_CMD_REG); r = wait_for_completion_interruptible_timeout(&bus->cmd_complete, bus->adap.timeout*HZ); if (bus->cmd_err != 0) { dev_dbg(bus->dev, "ERROR!! Failed to do recovery command(0x%08x)\n", bus->cmd_err); return -1; } //Check 0x14's SDA and SCL status sts = ast_i2c_read(bus,I2C_CMD_REG); if (sts & AST_I2CD_SDA_LINE_STS) //Recover OK break; } if (i == 10) { dev_dbg(bus->dev, "ERROR!! recover failed\n"); return -1; } } else { dev_dbg(bus->dev, "Don't know how to handle this case?!\n"); return -1; } dev_dbg(bus->dev, "Recovery successfully\n"); return 0; } static void ast_master_alert_recv(struct aspeed_i2c_bus *bus) { dev_dbg(bus->dev,"ast_master_alert_recv bus id %d, Disable Alt, Please Imple \n",bus->bus_id); } static int ast_i2c_wait_bus_not_busy(struct aspeed_i2c_bus *bus) { int timeout = 32; //TODO number while (ast_i2c_read(bus, I2C_CMD_REG) & AST_I2CD_BUS_BUSY_STS) { ast_i2c_bus_error_recover(bus); if(timeout <= 0) break; timeout--; msleep(2); } return timeout <= 0 ? EAGAIN : 0; } static void ast_i2c_do_byte_xfer(struct aspeed_i2c_bus *bus) { u8 *xfer_buf; u32 cmd = 0; bus->master_xfer_mode = BYTE_XFER; bus->master_xfer_len = 1; bus->slave_xfer_mode = BYTE_XFER; bus->slave_xfer_len = 1; dev_dbg(bus->dev, "ast_i2c_do_byte_xfer \n"); if (bus->slave_operation == 1) { dev_dbg(bus->dev, "S cnt %d, xf len %d \n", bus->slave_xfer_cnt, bus->slave_msgs->len); if (bus->slave_msgs->flags & I2C_M_RD) { //READ <-- TX dev_dbg(bus->dev, "(<--) slave(tx) buf %d [%x]\n", bus->slave_xfer_cnt, bus->slave_msgs->buf[bus->slave_xfer_cnt]); ast_i2c_write(bus, bus->slave_msgs->buf[bus->slave_xfer_cnt], I2C_BYTE_BUF_REG); ast_i2c_write(bus, AST_I2CD_S_TX_CMD, I2C_CMD_REG); } else { // Write -->Rx //no need to handle in byte mode dev_dbg(bus->dev, "(-->) slave(rx) BYTE do nothing\n"); } } else { dev_dbg(bus->dev,"M cnt %d, xf len %d \n", bus->master_xfer_cnt, bus->master_msgs->len); if(bus->master_xfer_cnt == -1) { //first start dev_dbg(bus->dev, " %sing %d byte%s %s 0x%02x\n", bus->master_msgs->flags & I2C_M_RD ? "read" : "write", bus->master_msgs->len, bus->master_msgs->len > 1 ? "s" : "", bus->master_msgs->flags & I2C_M_RD ? "from" : "to", bus->master_msgs->addr); if (bus->master_msgs->flags & I2C_M_RD) ast_i2c_write(bus, (bus->master_msgs->addr <<1) |0x1, I2C_BYTE_BUF_REG); else ast_i2c_write(bus, (bus->master_msgs->addr <<1), I2C_BYTE_BUF_REG); ast_i2c_write(bus, ast_i2c_read(bus,I2C_INTR_CTRL_REG) | AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ast_i2c_write(bus, AST_I2CD_M_TX_CMD | AST_I2CD_M_START_CMD, I2C_CMD_REG); } else if (bus->master_xfer_cnt < bus->master_msgs->len){ xfer_buf = bus->master_msgs->buf; if (bus->master_msgs->flags & I2C_M_RD) { //Rx data cmd = AST_I2CD_M_RX_CMD; if((bus->master_msgs->flags & I2C_M_RECV_LEN) && (bus->master_xfer_cnt == 0)) { dev_dbg(bus->dev, "I2C_M_RECV_LEN \n"); ast_i2c_write(bus, ast_i2c_read(bus,I2C_INTR_CTRL_REG) | AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); } else if((bus->xfer_last == 1) && (bus->master_xfer_cnt + 1 == bus->master_msgs->len)) { cmd |= AST_I2CD_M_S_RX_CMD_LAST | AST_I2CD_M_STOP_CMD; // disable rx_dwn isr ast_i2c_write(bus, ast_i2c_read(bus,I2C_INTR_CTRL_REG) & ~AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); } else { ast_i2c_write(bus, ast_i2c_read(bus,I2C_INTR_CTRL_REG) | AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); } dev_dbg(bus->dev, "(<--) rx byte, cmd = %x \n",cmd); ast_i2c_write(bus, cmd, I2C_CMD_REG); } else { //Tx data dev_dbg(bus->dev, "(-->) xfer byte data index[%02x]:%02x \n",bus->master_xfer_cnt, *(xfer_buf + bus->master_xfer_cnt)); ast_i2c_write(bus, *(xfer_buf + bus->master_xfer_cnt), I2C_BYTE_BUF_REG); if((bus->xfer_last == 1) && (bus->master_xfer_cnt + 1 == bus->master_msgs->len)) { ast_i2c_write(bus, ast_i2c_read(bus,I2C_INTR_CTRL_REG) & ~AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ast_i2c_write(bus, AST_I2CD_M_TX_CMD | AST_I2CD_M_STOP_CMD, I2C_CMD_REG); } else { ast_i2c_write(bus, ast_i2c_read(bus,I2C_INTR_CTRL_REG) | AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ast_i2c_write(bus, AST_I2CD_M_TX_CMD, I2C_CMD_REG); } } } else { //should send next msg if(bus->master_xfer_cnt != bus->master_msgs->len) dev_dbg(bus->dev,"CNT ERROR \n"); dev_dbg(bus->dev, "ast_i2c_do_byte_xfer complete \n"); bus->cmd_err = 0; complete(&bus->cmd_complete); } } } static void ast_i2c_slave_xfer_done(struct aspeed_i2c_bus *bus) { u32 xfer_len = 0; dev_dbg(bus->dev, "ast_i2c_slave_xfer_done [%d]\n",bus->slave_xfer_mode); if (bus->slave_msgs->flags & I2C_M_RD) { //tx done , only check tx count ... if(bus->slave_xfer_mode == BYTE_XFER) xfer_len = 1; else dev_dbg(bus->dev,"ERROR type !! \n"); } else { //rx done if (bus->slave_xfer_mode == BYTE_XFER) { //TODO xfer_len = 1; #ifdef CONFIG_AST_I2C_SLAVE_RDWR if (bus->slave_event == I2C_SLAVE_EVENT_STOP) { bus->slave_msgs->buf[bus->slave_xfer_cnt] = 0; bus->slave_msgs->len = bus->slave_xfer_cnt; } else { bus->slave_msgs->buf[bus->slave_xfer_cnt] = ast_i2c_read(bus,I2C_BYTE_BUF_REG) >> 8; } #else if (bus->slave_event != I2C_SLAVE_EVENT_STOP) bus->slave_msgs->buf[bus->slave_xfer_cnt] = ast_i2c_read(bus,I2C_BYTE_BUF_REG) >> 8; #endif dev_dbg(bus->dev,"rx buff %d, [%x] \n",bus->slave_xfer_cnt ,bus->slave_msgs->buf[bus->slave_xfer_cnt]); } else { dev_dbg(bus->dev,"ERROR !! XFER Type \n"); } } if (xfer_len != bus->slave_xfer_len) { dev_dbg(bus->dev, "slave not xfer complete should goto stop\n"); bus->slave_xfer_cnt += xfer_len; } else bus->slave_xfer_cnt += bus->slave_xfer_len; if ((bus->slave_event == I2C_SLAVE_EVENT_NACK) || (bus->slave_event == I2C_SLAVE_EVENT_STOP)) { #ifdef CONFIG_AST_I2C_SLAVE_RDWR ast_i2c_slave_rdwr_xfer(bus); #else bus->slave_xfer(bus->slave_event, &(bus->slave_msgs)); #endif bus->slave_xfer_cnt = 0; } else { dev_dbg(bus->dev,"bus->slave_xfer_cnt %d , bus->slave_msgs->len = %d \n",bus->slave_xfer_cnt, bus->slave_msgs->len); if (bus->slave_xfer_cnt == bus->slave_msgs->len) { dev_dbg(bus->dev,"slave next msgs \n"); #ifdef CONFIG_AST_I2C_SLAVE_RDWR ast_i2c_slave_rdwr_xfer(bus); #else bus->slave_xfer(bus->slave_event, &(bus->slave_msgs)); #endif bus->slave_xfer_cnt = 0; } bus->do_slave_xfer(bus); } //Issue workaround bus->state = (ast_i2c_read(bus,I2C_CMD_REG) >> 19) & 0xf; if(AST_I2CD_IDLE == bus->state) { dev_dbg(bus->dev,"** Slave go IDLE **\n"); bus->slave_operation = 0; } } //TX/Rx Done static void ast_i2c_master_xfer_done(struct aspeed_i2c_bus *bus) { u32 xfer_len = 0; dev_dbg(bus->dev, "ast_i2c_master_xfer_done mode[%d] %s\n", bus->master_xfer_mode, bus->master_msgs->flags & I2C_M_RD ? "read" : "write"); if (bus->master_msgs->flags & I2C_M_RD) { if (bus->master_xfer_cnt == -1) { xfer_len = 1; dev_dbg(bus->dev, "goto next_xfer \n"); goto next_xfer; } if (bus->master_xfer_mode == BYTE_XFER) { if ((bus->master_msgs->flags & I2C_M_RECV_LEN) && (bus->blk_r_flag == 0)) { bus->master_msgs->len += (ast_i2c_read(bus,I2C_BYTE_BUF_REG) & AST_I2CD_RX_BYTE_BUFFER) >> 8; bus->blk_r_flag = 1; dev_dbg(bus->dev, "I2C_M_RECV_LEN %d \n", bus->master_msgs->len -1); } xfer_len = 1; bus->master_msgs->buf[bus->master_xfer_cnt] = (ast_i2c_read(bus,I2C_BYTE_BUF_REG) & AST_I2CD_RX_BYTE_BUFFER) >> 8; } else { dev_dbg(bus->dev,"ERROR xfer type \n"); } } else { if (bus->master_xfer_mode == BYTE_XFER) xfer_len = 1; else dev_dbg(bus->dev,"ERROR xfer type \n"); } next_xfer: if (xfer_len != bus->master_xfer_len) { //TODO.. dev_dbg(bus->dev," ** xfer_len = %d != master_xfer_len = %d \n", xfer_len, bus->master_xfer_len); //should goto stop.... bus->cmd_err = 1; goto done_out; } else bus->master_xfer_cnt += bus->master_xfer_len; if (bus->master_xfer_cnt != bus->master_msgs->len) { dev_dbg(bus->dev,"do next cnt \n"); bus->do_master_xfer(bus); } else { bus->cmd_err = 0; done_out: dev_dbg(bus->dev,"msgs complete \n"); complete(&bus->cmd_complete); } } static void ast_i2c_slave_addr_match(struct aspeed_i2c_bus *bus) { u8 match; bus->slave_operation = 1; bus->slave_xfer_cnt = 0; match = ast_i2c_read(bus,I2C_BYTE_BUF_REG) >> 8; bus->slave_msgs->buf[0] = match; dev_dbg(bus->dev, "S Start Addr match [%x] \n",match); if(match & 1) { bus->slave_event = I2C_SLAVE_EVENT_START_READ; } else { bus->slave_event = I2C_SLAVE_EVENT_START_WRITE; } #ifdef CONFIG_AST_I2C_SLAVE_RDWR ast_i2c_slave_rdwr_xfer(bus); bus->slave_msgs->buf[0] = match; bus->slave_xfer_cnt = 1; #else bus->slave_xfer(bus->slave_event, &(bus->slave_msgs)); bus->slave_xfer_cnt = 0; #endif bus->do_slave_xfer = ast_i2c_do_byte_xfer; bus->do_slave_xfer_done = ast_i2c_slave_xfer_done; bus->do_slave_xfer(bus); } static irqreturn_t aspeed_i2c_bus_irq_handle(struct aspeed_i2c_bus *bus) { u32 sts; bus->state = (ast_i2c_read(bus, I2C_CMD_REG) >> 19) & 0xf; sts = ast_i2c_read(bus, I2C_INTR_STS_REG); //Ryan Fix for Issue No one care .. sts &= 0xff; // printk("ISR : %x \n",sts); if (AST_I2CD_INTR_STS_SMBUS_ALT & sts) { dev_dbg(bus->dev, "M clear isr: AST_I2CD_INTR_STS_SMBUS_ALT= %x\n", sts); //Disable ALT INT ast_i2c_write(bus, ast_i2c_read(bus, I2C_INTR_CTRL_REG) & ~AST_I2CD_SMBUS_ALT_INTR_EN, I2C_INTR_CTRL_REG); ast_i2c_write(bus, AST_I2CD_INTR_STS_SMBUS_ALT, I2C_INTR_STS_REG); ast_master_alert_recv(bus); sts &= ~AST_I2CD_SMBUS_ALT_INTR_EN; } switch(sts) { case AST_I2CD_INTR_STS_TX_ACK: if(bus->slave_operation == 1) { bus->slave_event = I2C_SLAVE_EVENT_READ; ast_i2c_slave_xfer_done(bus); dev_dbg(bus->dev, "S clear isr: AST_I2CD_INTR_STS_TX_ACK = %x\n",sts); ast_i2c_write(bus, AST_I2CD_INTR_STS_TX_ACK, I2C_INTR_STS_REG); } else { dev_dbg(bus->dev, "M clear isr: AST_I2CD_INTR_STS_TX_ACK = %x\n",sts); ast_i2c_write(bus, AST_I2CD_INTR_STS_TX_ACK, I2C_INTR_STS_REG); ast_i2c_master_xfer_done(bus); } break; case AST_I2CD_INTR_STS_TX_ACK | AST_I2CD_INTR_STS_NORMAL_STOP: if ((bus->xfer_last == 1) && (bus->slave_operation == 0)) { dev_dbg(bus->dev, "M clear isr: AST_I2CD_INTR_STS_TX_ACK | AST_I2CD_INTR_STS_NORMAL_STOP= %x\n",sts); ast_i2c_write(bus, AST_I2CD_INTR_STS_TX_ACK | AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG); //take care ast_i2c_write(bus, ast_i2c_read(bus,I2C_INTR_CTRL_REG) | AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ast_i2c_master_xfer_done(bus); } else { dev_dbg(bus->dev,"TODO ...\n"); } break; case AST_I2CD_INTR_STS_TX_NAK: if (bus->slave_operation == 1) { bus->slave_event = I2C_SLAVE_EVENT_NACK; ast_i2c_slave_xfer_done(bus); dev_dbg(bus->dev, "S clear isr: AST_I2CD_INTR_STS_TX_NAK = %x\n",sts); ast_i2c_write(bus, AST_I2CD_INTR_STS_TX_NAK, I2C_INTR_STS_REG); } else { dev_dbg(bus->dev, "M clear isr: AST_I2CD_INTR_STS_TX_NAK = %x\n",sts); ast_i2c_write(bus, AST_I2CD_INTR_STS_TX_NAK, I2C_INTR_STS_REG); if(bus->master_msgs->flags == I2C_M_IGNORE_NAK) { dev_dbg(bus->dev, "I2C_M_IGNORE_NAK next send\n"); bus->cmd_err = 0; } else { dev_dbg(bus->dev, "NAK error\n"); bus->cmd_err = AST_I2CD_INTR_STS_TX_NAK; } complete(&bus->cmd_complete); } break; case AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_NORMAL_STOP: if (bus->slave_operation == 1) { dev_dbg(bus->dev,"SLAVE TODO .... \n"); } else { dev_dbg(bus->dev, "M clear isr: AST_I2CD_INTR_STS_TX_NAK| AST_I2CD_INTR_STS_NORMAL_STOP = %x\n",sts); ast_i2c_write(bus, AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG); dev_dbg(bus->dev, "M TX NAK | NORMAL STOP \n"); bus->cmd_err = AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_NORMAL_STOP; complete(&bus->cmd_complete); } break; //Issue : Workaround for I2C slave mode case AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_SLAVE_MATCH: if (bus->slave_operation == 1) { bus->slave_event = I2C_SLAVE_EVENT_NACK; ast_i2c_slave_xfer_done(bus); ast_i2c_slave_addr_match(bus); ast_i2c_write(bus, AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_SLAVE_MATCH , I2C_INTR_STS_REG); } else { dev_dbg(bus->dev,"ERROR !!!!\n"); } break; case AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_SLAVE_MATCH: ast_i2c_slave_addr_match(bus); dev_dbg(bus->dev, "S clear isr: AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_SLAVE_MATCH = %x\n",sts); ast_i2c_write(bus, AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_SLAVE_MATCH, I2C_INTR_STS_REG); break; case AST_I2CD_INTR_STS_RX_DOWN: if (bus->slave_operation == 1) { bus->slave_event = I2C_SLAVE_EVENT_WRITE; ast_i2c_slave_xfer_done(bus); dev_dbg(bus->dev, "S clear isr: AST_I2CD_INTR_STS_RX_DOWN = %x\n",sts); ast_i2c_write(bus, AST_I2CD_INTR_STS_RX_DOWN, I2C_INTR_STS_REG); } else { dev_dbg(bus->dev, "M clear isr: AST_I2CD_INTR_STS_RX_DOWN = %x\n",sts); ast_i2c_write(bus, AST_I2CD_INTR_STS_RX_DOWN, I2C_INTR_STS_REG); ast_i2c_master_xfer_done(bus); } break; case AST_I2CD_INTR_STS_NORMAL_STOP: if (bus->slave_operation == 1) { bus->slave_event = I2C_SLAVE_EVENT_STOP; ast_i2c_slave_xfer_done(bus); dev_dbg(bus->dev, "S clear isr: AST_I2CD_INTR_STS_NORMAL_STOP = %x\n",sts); ast_i2c_write(bus, AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG); dev_dbg(bus->dev, "state [%x] \n",bus->state); } else { dev_dbg(bus->dev, "M clear isr: AST_I2CD_INTR_STS_NORMAL_STOP = %x\n",sts); ast_i2c_write(bus, AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG); bus->cmd_err = 0; complete(&bus->cmd_complete); } break; case (AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_NORMAL_STOP): if ((bus->xfer_last == 1) && (bus->slave_operation == 0)) { dev_dbg(bus->dev, "M clear isr: AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_NORMAL_STOP = %x\n",sts); ast_i2c_write(bus, AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG); //take care ast_i2c_write(bus, ast_i2c_read(bus,I2C_INTR_CTRL_REG) | AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); ast_i2c_master_xfer_done(bus); } else { dev_dbg(bus->dev,"TODO .. .. ..\n"); } break; case AST_I2CD_INTR_STS_ARBIT_LOSS: dev_dbg(bus->dev, "M clear isr: AST_I2CD_INTR_STS_ARBIT_LOSS = %x\n",sts); ast_i2c_write(bus, AST_I2CD_INTR_STS_ARBIT_LOSS, I2C_INTR_STS_REG); bus->cmd_err = AST_I2CD_INTR_STS_ARBIT_LOSS; complete(&bus->cmd_complete); break; case AST_I2CD_INTR_STS_ABNORMAL: bus->cmd_err = AST_I2CD_INTR_STS_ABNORMAL; complete(&bus->cmd_complete); break; case AST_I2CD_INTR_STS_SCL_TO: bus->cmd_err = AST_I2CD_INTR_STS_SCL_TO; complete(&bus->cmd_complete); break; case AST_I2CD_INTR_STS_GCALL_ADDR: bus->cmd_err = AST_I2CD_INTR_STS_GCALL_ADDR; complete(&bus->cmd_complete); break; case AST_I2CD_INTR_STS_SMBUS_DEF_ADDR: break; case AST_I2CD_INTR_STS_SMBUS_DEV_ALT: break; case AST_I2CD_INTR_STS_SMBUS_ARP_ADDR: break; case AST_I2CD_INTR_STS_SDA_DL_TO: break; case AST_I2CD_INTR_STS_BUS_RECOVER: dev_dbg(bus->dev, "M clear isr: AST_I2CD_INTR_STS_BUS_RECOVER= %x\n",sts); ast_i2c_write(bus, AST_I2CD_INTR_STS_BUS_RECOVER, I2C_INTR_STS_REG); bus->cmd_err = 0; complete(&bus->cmd_complete); break; default: dev_err(bus->dev, "GR %p : No one care : %x, bus_id %d\n", bus->i2c_dev->reg_gr, sts, bus->bus_id); return IRQ_NONE; } return IRQ_HANDLED; } static irqreturn_t i2c_ast_handler(int this_irq, void *data) { unsigned int p; unsigned long isr_sts; struct ast_i2c_dev *i2c = data; isr_sts = readl(i2c->reg_gr); for_each_set_bit(p, &isr_sts, 14) aspeed_i2c_bus_irq_handle(&i2c->buses[p]); /* TODO: use a proper irq chip so we can return the status from each handler? */ return IRQ_HANDLED; } static int ast_i2c_do_msgs_xfer(struct aspeed_i2c_bus *bus, struct i2c_msg *msgs, int num) { int i; int ret = 0; bus->do_master_xfer = ast_i2c_do_byte_xfer; for (i = 0; i < num; i++) { bus->blk_r_flag = 0; bus->master_msgs = &msgs[i]; if(num == i+1) bus->xfer_last = 1; else bus->xfer_last = 0; bus->blk_r_flag = 0; init_completion(&bus->cmd_complete); if(bus->master_msgs->flags & I2C_M_NOSTART) bus->master_xfer_cnt = 0; else bus->master_xfer_cnt = -1; bus->do_master_xfer(bus); ret = wait_for_completion_interruptible_timeout( &bus->cmd_complete, bus->adap.timeout * HZ); if (ret == 0) { dev_dbg(bus->dev, "controller timed out\n"); bus->state = (ast_i2c_read(bus,I2C_CMD_REG) >> 19) & 0xf; ret = -ETIMEDOUT; goto stop; } if (bus->cmd_err != 0) { if (bus->cmd_err == (AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_NORMAL_STOP)) { dev_dbg(bus->dev, "go out \n"); ret = -ETIMEDOUT; goto out; } else { dev_dbg(bus->dev, "send stop \n"); ret = -EAGAIN; goto stop; } } ret++; } if(bus->cmd_err == 0) goto out; stop: init_completion(&bus->cmd_complete); ast_i2c_write(bus, AST_I2CD_M_STOP_CMD, I2C_CMD_REG); wait_for_completion_interruptible_timeout(&bus->cmd_complete, bus->adap.timeout*HZ); out: dev_dbg(bus->dev, "end xfer ret = %d, xfer mode[%d]\n", ret, bus->master_xfer_mode); return ret; } static int ast_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) { struct aspeed_i2c_bus *bus = adap->algo_data; int ret, i; int sts; sts = ast_i2c_read(bus, I2C_CMD_REG); dev_dbg(bus->dev, "state[%x], SCL[%d], SDA[%d], BUS[%d]\n", (sts >> 19) & 0xf, (sts >> 18) & 0x1, (sts >> 17) & 0x1, (sts >> 16) & 1); /* * Wait for the bus to become free. */ ret = ast_i2c_wait_bus_not_busy(bus); if (ret) { dev_err(&adap->dev, "i2c_ast: timeout waiting for bus free\n"); goto out; } for (i = adap->retries; i >= 0; i--) { if (i != 0) dev_dbg(&adap->dev, "Do retrying transmission [%d]\n",i); ret = ast_i2c_do_msgs_xfer(bus, msgs, num); if (ret != -EAGAIN) goto out; udelay(100); } ret = -EREMOTEIO; out: return ret; } static u32 ast_i2c_functionality(struct i2c_adapter *adap) { return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_BLOCK_DATA; } static const struct i2c_algorithm i2c_ast_algorithm = { .master_xfer = ast_i2c_xfer, #ifdef CONFIG_AST_I2C_SLAVE_RDWR .slave_xfer = ast_i2c_slave_xfer, #endif .functionality = ast_i2c_functionality, }; static int aspeed_i2c_add_bus(struct device_node *np, struct ast_i2c_dev *i2c, struct platform_device *pdev) { struct aspeed_i2c_bus *bus; struct resource res; int ret, bus_num; ret = of_property_read_u32(np, "bus", &bus_num); if (ret || bus_num >= ARRAY_SIZE(i2c->buses)) return -ENXIO; bus = &i2c->buses[bus_num]; ret = of_address_to_resource(np, 0, &res); if (ret < 0) return -ENXIO; bus->base = devm_ioremap_resource(&pdev->dev, &res); if (IS_ERR(bus->base)) return PTR_ERR(bus->base); /* Initialize the I2C adapter */ bus->adap.nr = bus_num; bus->adap.owner = THIS_MODULE; bus->adap.retries = 0; bus->adap.timeout = 5; bus->adap.algo = &i2c_ast_algorithm; bus->adap.algo_data = bus; bus->adap.dev.parent = &pdev->dev; bus->adap.dev.of_node = np; snprintf(bus->adap.name, sizeof(bus->adap.name), "Aspeed i2c at %p", bus->base); bus->master_xfer_mode = BYTE_XFER; bus->slave_operation = 0; bus->blk_r_flag = 0; bus->bus_id = bus_num; /* TODO: fix */ bus->dev = i2c->dev; bus->i2c_dev = i2c; ret = of_property_read_u32(np, "clock-frequency", &bus->bus_clk); if (ret < 0) { dev_err(&pdev->dev, "Could not read clock-frequency property\n"); bus->bus_clk = 100000; } ast_i2c_dev_init(bus); #ifdef CONFIG_AST_I2C_SLAVE_RDWR ast_i2c_slave_buff_init(bus); #endif ret = i2c_add_numbered_adapter(&bus->adap); if (ret < 0) return -ENXIO; return 0; } static int ast_i2c_probe(struct platform_device *pdev) { struct ast_i2c_dev *dev; struct resource *res; struct device_node *np; int ret; dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) return -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); dev->reg_gr = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(dev->reg_gr)) return PTR_ERR(dev->reg_gr); dev->irq = platform_get_irq(pdev, 0); if (dev->irq < 0) return -ENXIO; ret = request_irq(dev->irq, i2c_ast_handler, IRQF_SHARED, "Apseed i2c", dev); if (ret) return -ENXIO; dev->dev = &pdev->dev; dev->pclk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(dev->pclk)) { dev_err(&pdev->dev, "cannot get pclk for i2c\n"); return PTR_ERR(dev->pclk); } for_each_available_child_of_node(pdev->dev.of_node, np) { if (!of_device_is_compatible(np, "aspeed,ast2400-i2c-bus")) continue; ret = aspeed_i2c_add_bus(np, dev, pdev); if (ret < 0) dev_err(&pdev->dev, "faield to add i2c bus %s\n", np->name); } platform_set_drvdata(pdev, dev); return 0; } static const struct of_device_id aspeed_i2c_of_table[] = { { .compatible = "aspeed,ast2400-i2c-common", }, { }, }; MODULE_DEVICE_TABLE(of, aspeed_i2c_of_table); static struct platform_driver i2c_ast_driver = { .probe = ast_i2c_probe, .driver = { .name = KBUILD_MODNAME, .of_match_table = aspeed_i2c_of_table, }, }; module_platform_driver(i2c_ast_driver); MODULE_AUTHOR("Ryan Chen "); MODULE_DESCRIPTION("ASPEED AST I2C Bus Driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:ast_i2c");