diff options
author | Tian Fang <tfang@fb.com> | 2015-12-14 22:08:40 -0800 |
---|---|---|
committer | Tian Fang <tfang@fb.com> | 2015-12-15 09:49:21 -0800 |
commit | e65a7944211c70f6b5cfb6cedd73cc31105319de (patch) | |
tree | 067082251bc52bc6c09ca87feaa1352d0468a5ac /meta-aspeed/recipes-kernel | |
parent | 8a67fbdd0e251bb34d55992b0771edba1837d589 (diff) | |
download | ast2050-yocto-openbmc-e65a7944211c70f6b5cfb6cedd73cc31105319de.zip ast2050-yocto-openbmc-e65a7944211c70f6b5cfb6cedd73cc31105319de.tar.gz |
Sync to internal OpenBMC repo f926614
Diffstat (limited to 'meta-aspeed/recipes-kernel')
3 files changed, 1013 insertions, 20 deletions
diff --git a/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0033-Linux-snapshot-of-OpenBMC-f926614.patch b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0033-Linux-snapshot-of-OpenBMC-f926614.patch new file mode 100644 index 0000000..4e4c76e --- /dev/null +++ b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0033-Linux-snapshot-of-OpenBMC-f926614.patch @@ -0,0 +1,978 @@ +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/plat-aspeed/dev-i2c.c b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/plat-aspeed/dev-i2c.c +index fffa480..a6f75b1 100644 +--- a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/plat-aspeed/dev-i2c.c ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/plat-aspeed/dev-i2c.c +@@ -634,6 +634,9 @@ static struct i2c_board_info __initdata wedge100_i2c_bus5[] = { + { + I2C_BOARD_INFO("fb_panther_plus", 0x40), + }, ++ { ++ I2C_BOARD_INFO("com_e_driver", 0x33), ++ } + }; + + static struct i2c_board_info __initdata wedge100_i2c_bus6[] = { +@@ -767,11 +770,17 @@ static struct i2c_board_info __initdata ast_i2c_board_info_11[] = { + //Under I2C Dev 12 + static struct i2c_board_info __initdata ast_i2c_board_info_12[] = { + // Mezz Card LAN_SMB bus (PHY, Temp. Sensor) ++ { ++ //I2C_BOARD_INFO("tmp75", 0x1f), ++ }, + }; + + //Under I2C Dev 13 + static struct i2c_board_info __initdata ast_i2c_board_info_13[] = { + // Mezz Card Mezz_SMB bus (FRUID, GPIO expander, QSFP+) ++ { ++ I2C_BOARD_INFO("24c64", 0x51), ++ }, + }; + + /* end of CONFIG_YOSEMITE */ +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/hwmon/ast_adc.c b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/hwmon/ast_adc.c +index 8f5aa54..e21d52e 100644 +--- a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/hwmon/ast_adc.c ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/hwmon/ast_adc.c +@@ -525,7 +525,7 @@ ast_show_adc(struct device *dev, struct device_attribute *attr, char *sysfsbuf) + break; + case 1: //value + voltage = ast_get_voltage(sensor_attr->index); +- return sprintf(sysfsbuf, "%d.%d (V)\n",voltage/100, voltage%100); ++ return sprintf(sysfsbuf, "%d.%02d (V)\n",voltage/100, voltage%100); + break; + case 2: //alarm + return sprintf(sysfsbuf, "%d \n", ast_get_adc_alarm(ast_adc,sensor_attr->index)); +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/i2c/busses/i2c-ast.c b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/i2c/busses/i2c-ast.c +index 9bb3154..48f0192 100644 +--- a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/i2c/busses/i2c-ast.c ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/i2c/busses/i2c-ast.c +@@ -49,14 +49,22 @@ + /***************************************************************************/ + + #ifdef CONFIG_AST_I2C_SLAVE_RDWR +-#define I2C_S_BUF_SIZE 64 +-#define I2C_S_RX_BUF_NUM 4 ++#define I2C_S_BUF_SIZE 256 ++#define I2C_S_RX_BUF_NUM 20 + #define BUFF_FULL 0xff00 + #define BUFF_ONGOING 1 + #endif + + #define AST_LOCKUP_DETECTED (0x1 << 15) + ++// Enable SCL/SDA pull LOW detection for Yosemite platform ++#ifdef CONFIG_YOSEMITE ++#define AST_I2C_LOW_TIMEOUT 0x07 ++#else ++#define AST_I2C_LOW_TIMEOUT 0x00 ++#endif //CONFIG_YOSEMITE ++ ++ + struct ast_i2c_dev { + struct ast_i2c_driver_data *ast_i2c_data; + struct device *dev; +@@ -192,12 +200,12 @@ static void ast_i2c_dev_init(struct ast_i2c_dev *i2c_dev) + , I2C_FUN_CTRL_REG); + + /* Set AC Timing */ +- ast_i2c_write(i2c_dev, 0x3, I2C_AC_TIMING_REG2); ++ ast_i2c_write(i2c_dev, AST_I2C_LOW_TIMEOUT, I2C_AC_TIMING_REG2); + ast_i2c_write(i2c_dev, select_i2c_clock(i2c_dev), I2C_AC_TIMING_REG1); + }else { + /* target apeed is xxKhz*/ + ast_i2c_write(i2c_dev, select_i2c_clock(i2c_dev), I2C_AC_TIMING_REG1); +- ast_i2c_write(i2c_dev, AST_NO_TIMEOUT_CTRL, I2C_AC_TIMING_REG2); ++ ast_i2c_write(i2c_dev, AST_I2C_LOW_TIMEOUT, I2C_AC_TIMING_REG2); + } + #else + /* target apeed is xxKhz*/ +@@ -252,6 +260,7 @@ static void ast_i2c_slave_buff_init(struct ast_i2c_dev *i2c_dev) + static void ast_i2c_slave_rdwr_xfer(struct ast_i2c_dev *i2c_dev) + { + int i; ++ int count = 0; + unsigned long flags; + + spin_lock_irqsave(&i2c_dev->slave_rx_lock, flags); +@@ -265,15 +274,31 @@ static void ast_i2c_slave_rdwr_xfer(struct ast_i2c_dev *i2c_dev) + } + } + if(i == I2C_S_RX_BUF_NUM) { +- printk("RX buffer full ........use tmp msgs buff \n"); +- //TODO... ++ // dev_err(i2c_dev->dev, "RX buffer full ........use tmp msgs buff \n"); ++ for(i=0; i<I2C_S_RX_BUF_NUM; i++) { ++ if((i2c_dev->slave_rx_msg[i].flags == 0) && (i2c_dev->slave_rx_msg[i].addr == BUFF_ONGOING)) { ++ count++; ++ i2c_dev->slave_rx_msg[i].addr = 0; ++ } ++ } ++ ++ if (count) { ++ dev_err(i2c_dev->dev, "Cleared slave ongoing buffers of count: %d\n", count); ++ } ++ ++ for(i=0; i<I2C_S_RX_BUF_NUM; i++) { ++ if((i2c_dev->slave_rx_msg[i].flags == 0) && (i2c_dev->slave_rx_msg[i].addr != BUFF_ONGOING)) { ++ i2c_dev->slave_rx_msg[i].addr = BUFF_ONGOING; ++ break; ++ } ++ } + } + //printk("I2C_SLAVE_EVENT_START_WRITE ... %d \n", i); + + i2c_dev->slave_msgs = &i2c_dev->slave_rx_msg[i]; + break; + case I2C_SLAVE_EVENT_START_READ: +- //printk("I2C_SLAVE_EVENT_START_READ ERROR .. not imple \n"); ++ // printk("I2C_SLAVE_EVENT_START_READ ERROR .. not imple \n"); + i2c_dev->slave_msgs = &i2c_dev->slave_tx_msg; + break; + case I2C_SLAVE_EVENT_WRITE: +@@ -379,17 +404,17 @@ ast_i2c_bus_error_recover(struct ast_i2c_dev *i2c_dev) + + if ((sts & AST_I2CD_SDA_LINE_STS) && (sts & AST_I2CD_SCL_LINE_STS)) { + //Means bus is idle. +- dev_dbg(i2c_dev->dev, "I2C bus (%d) is idle. I2C slave doesn't exist?!\n", i2c_dev->bus_id); ++ dev_err(i2c_dev->dev, "I2C bus (%d) is idle. I2C slave doesn't exist?!\n", i2c_dev->bus_id); + return -1; + } + +- dev_dbg(i2c_dev->dev, "ERROR!! I2C(%d) bus hanged, try to recovery it!\n", i2c_dev->bus_id); ++ dev_err(i2c_dev->dev, "ERROR!! I2C(%d) bus hanged, try to recovery it!\n", i2c_dev->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(i2c_dev->dev, "I2C's master is locking the bus, try to stop it.\n"); ++ dev_err(i2c_dev->dev, "I2C's master is locking the bus, try to stop it.\n"); + // + init_completion(&i2c_dev->cmd_complete); + i2c_dev->cmd_err = 0; +@@ -401,15 +426,15 @@ ast_i2c_bus_error_recover(struct ast_i2c_dev *i2c_dev) + + if(i2c_dev->cmd_err && + i2c_dev->cmd_err != AST_I2CD_INTR_STS_NORMAL_STOP) { +- dev_dbg(i2c_dev->dev, "recovery error \n"); ++ dev_err(i2c_dev->dev, "recovery error \n"); + return -1; + } + + if (r == 0) { +- dev_dbg(i2c_dev->dev, "recovery timed out\n"); ++ dev_err(i2c_dev->dev, "recovery timed out\n"); + return -1; + } else { +- dev_dbg(i2c_dev->dev, "Recovery successfully\n"); ++ dev_err(i2c_dev->dev, "Recovery successfully\n"); + return 0; + } + +@@ -417,19 +442,20 @@ ast_i2c_bus_error_recover(struct ast_i2c_dev *i2c_dev) + } 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(i2c_dev->dev, "I2C's slave is dead, try to recover it\n"); ++ dev_err(i2c_dev->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(i2c_dev); + //Do the recovery command BIT11 + init_completion(&i2c_dev->cmd_complete); ++ i2c_dev->cmd_err = 0; + ast_i2c_write(i2c_dev, AST_I2CD_BUS_RECOVER_CMD_EN, I2C_CMD_REG); + + r = wait_for_completion_interruptible_timeout(&i2c_dev->cmd_complete, + i2c_dev->adap.timeout*HZ); + if (i2c_dev->cmd_err != 0 && + i2c_dev->cmd_err != AST_I2CD_INTR_STS_NORMAL_STOP) { +- dev_dbg(i2c_dev->dev, "ERROR!! Failed to do recovery command(0x%08x)\n", i2c_dev->cmd_err); ++ dev_err(i2c_dev->dev, "ERROR!! Failed to do recovery command(0x%08x)\n", i2c_dev->cmd_err); + return -1; + } + //Check 0x14's SDA and SCL status +@@ -438,14 +464,14 @@ ast_i2c_bus_error_recover(struct ast_i2c_dev *i2c_dev) + break; + } + if (i == 10) { +- dev_dbg(i2c_dev->dev, "ERROR!! recover failed\n"); ++ dev_err(i2c_dev->dev, "ERROR!! recover failed\n"); + return -1; + } + } else { +- dev_dbg(i2c_dev->dev, "Don't know how to handle this case?!\n"); ++ dev_err(i2c_dev->dev, "Don't know how to handle this case?!\n"); + return -1; + } +- dev_dbg(i2c_dev->dev, "Recovery successfully\n"); ++ dev_err(i2c_dev->dev, "Recovery successfully\n"); + return 0; + } + +@@ -472,7 +498,8 @@ static int ast_i2c_wait_bus_not_busy(struct ast_i2c_dev *i2c_dev) + } + + if (timeout <= 0) { +- return -EAGAIN; ++ //TODO: sometimes the slave operation flag is not reset properly so go ahead with checking bus busy signal ++ dev_err(i2c_dev->dev, "slave operation set, check busy status line\n"); + } + + // Wait for Bus to go IDLE +@@ -491,6 +518,8 @@ static int ast_i2c_wait_bus_not_busy(struct ast_i2c_dev *i2c_dev) + return 0; + } + ++ // TODO: hack to reset slave operation flag manually ++ i2c_dev->slave_operation = 0; + return 0; + } + +@@ -499,9 +528,6 @@ static void ast_i2c_do_dma_xfer(struct ast_i2c_dev *i2c_dev) + u32 cmd = 0; + int i; + +- i2c_dev->master_xfer_mode = DMA_XFER; +- i2c_dev->slave_xfer_mode = DMA_XFER; +- + if(i2c_dev->slave_operation == 1) { + if(i2c_dev->slave_msgs->flags & I2C_M_RD) { + //DMA tx mode +@@ -683,9 +709,6 @@ static void ast_i2c_do_pool_xfer(struct ast_i2c_dev *i2c_dev) + int i; + u32 *tx_buf; + +- i2c_dev->master_xfer_mode = BUFF_XFER; +- i2c_dev->slave_xfer_mode = BUFF_XFER; +- + #if defined(CONFIG_ARCH_AST2400) + ast_i2c_write(i2c_dev, + (ast_i2c_read(i2c_dev, I2C_FUN_CTRL_REG) & +@@ -872,12 +895,6 @@ static void ast_i2c_do_byte_xfer(struct ast_i2c_dev *i2c_dev) + u8 *xfer_buf; + u32 cmd = 0; + +- i2c_dev->master_xfer_mode = BYTE_XFER; +- i2c_dev->master_xfer_len = 1; +- +- i2c_dev->slave_xfer_mode = BYTE_XFER; +- i2c_dev->slave_xfer_len = 1; +- + if(i2c_dev->slave_operation == 1) { + dev_dbg(i2c_dev->dev,"S cnt %d, xf len %d \n",i2c_dev->slave_xfer_cnt, i2c_dev->slave_msgs->len); + if(i2c_dev->slave_msgs->flags & I2C_M_RD) { +@@ -973,14 +990,16 @@ static void ast_i2c_slave_xfer_done(struct ast_i2c_dev *i2c_dev) + u32 xfer_len; + int i; + u8 *rx_buf; ++ unsigned long flags; + + dev_dbg(i2c_dev->dev, "ast_i2c_slave_xfer_done [%d]\n",i2c_dev->slave_xfer_mode); + ++ + if (i2c_dev->slave_msgs->flags & I2C_M_RD) { + //tx done , only check tx count ... +- if(i2c_dev->master_xfer_mode == BYTE_XFER) { ++ if(i2c_dev->slave_xfer_mode == BYTE_XFER) { + xfer_len = 1; +- } else if (i2c_dev->master_xfer_mode == BUFF_XFER) { ++ } else if (i2c_dev->slave_xfer_mode == BUFF_XFER) { + xfer_len = AST_I2CD_TX_DATA_BUF_GET(ast_i2c_read(i2c_dev, I2C_BUF_CTRL_REG)); + xfer_len++; + dev_dbg(i2c_dev->dev,"S tx buff done len %d \n",xfer_len); +@@ -1004,10 +1023,12 @@ static void ast_i2c_slave_xfer_done(struct ast_i2c_dev *i2c_dev) + i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt] = 0; + i2c_dev->slave_msgs->len = i2c_dev->slave_xfer_cnt; + } else { ++ if (i2c_dev->slave_xfer_cnt == 0) ++ dev_err(i2c_dev->dev,"Possible first byte failure issue\n"); + i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt] = ast_i2c_read(i2c_dev,I2C_BYTE_BUF_REG) >> 8; + } + dev_dbg(i2c_dev->dev,"rx buff %d, [%x] \n",i2c_dev->slave_xfer_cnt ,i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt]); +- } else if (i2c_dev->master_xfer_mode == BUFF_XFER) { ++ } else if (i2c_dev->slave_xfer_mode == BUFF_XFER) { + xfer_len = AST_I2CD_RX_BUF_ADDR_GET(ast_i2c_read(i2c_dev, I2C_BUF_CTRL_REG)); + if(xfer_len == 0) + xfer_len = AST_I2C_PAGE_SIZE; +@@ -1056,7 +1077,7 @@ static void ast_i2c_slave_xfer_done(struct ast_i2c_dev *i2c_dev) + i2c_dev->slave_xfer_cnt = 0; + } else { + if(i2c_dev->slave_xfer_cnt == i2c_dev->slave_msgs->len) { +- dev_dbg(i2c_dev->dev,"slave next msgs \n"); ++ dev_err(i2c_dev->dev,"slave next msgs with len %d\n", i2c_dev->slave_xfer_cnt); + #ifdef CONFIG_AST_I2C_SLAVE_RDWR + ast_i2c_slave_rdwr_xfer(i2c_dev); + #else +@@ -1068,6 +1089,8 @@ static void ast_i2c_slave_xfer_done(struct ast_i2c_dev *i2c_dev) + i2c_dev->do_slave_xfer(i2c_dev); + } + ++ // Read the current state for clearing up the slave mode ++ i2c_dev->state = (ast_i2c_read(i2c_dev,I2C_CMD_REG) >> 19) & 0xf; + + if(AST_I2CD_IDLE == i2c_dev->state) { + dev_dbg(i2c_dev->dev,"** Slave go IDLE **\n"); +@@ -1077,7 +1100,10 @@ static void ast_i2c_slave_xfer_done(struct ast_i2c_dev *i2c_dev) + i2c_dev->ast_i2c_data->free_pool_buff_page(i2c_dev->req_page); + } + +- } ++ } else if (i2c_dev->slave_event == I2C_SLAVE_EVENT_STOP) { ++ // TODO: hack to reset slave operation flag in case the stop is received ++ i2c_dev->slave_operation = 0; ++ } + + } + +@@ -1212,6 +1238,8 @@ unlock_out: + static void ast_i2c_slave_addr_match(struct ast_i2c_dev *i2c_dev) + { + u8 match; ++ unsigned long flags; ++ + + i2c_dev->slave_operation = 1; + i2c_dev->slave_xfer_cnt = 0; +@@ -1219,7 +1247,6 @@ static void ast_i2c_slave_addr_match(struct ast_i2c_dev *i2c_dev) + i2c_dev->slave_msgs->buf[0] = match; + dev_dbg(i2c_dev->dev, "S Start Addr match [%x] \n",match); + +- + if(match & 1) { + i2c_dev->slave_event = I2C_SLAVE_EVENT_START_READ; + } else { +@@ -1228,23 +1255,33 @@ static void ast_i2c_slave_addr_match(struct ast_i2c_dev *i2c_dev) + + #ifdef CONFIG_AST_I2C_SLAVE_RDWR + ast_i2c_slave_rdwr_xfer(i2c_dev); +- i2c_dev->slave_msgs->buf[0] = match; +- i2c_dev->slave_xfer_cnt = 1; ++ i2c_dev->slave_msgs->buf[0] = match; ++ i2c_dev->slave_xfer_cnt = 1; ++ // Reset the length field as we have received new slave address match ++ i2c_dev->slave_msgs->len = 0x0; + #else + i2c_dev->ast_i2c_data->slave_xfer(i2c_dev->slave_event, &(i2c_dev->slave_msgs)); + i2c_dev->slave_xfer_cnt = 0; + #endif + +- //request +- if(i2c_dev->ast_i2c_data->slave_dma == BYTE_MODE) ++ //request: set slave_xfer_mode properly based on slave_dma mode ++ if(i2c_dev->ast_i2c_data->slave_dma == BYTE_MODE) { + i2c_dev->do_slave_xfer = ast_i2c_do_byte_xfer; +- else if (i2c_dev->ast_i2c_data->slave_dma == DMA_MODE) ++ i2c_dev->slave_xfer_mode = BYTE_XFER; ++ i2c_dev->slave_xfer_len = 1; ++ } else if (i2c_dev->ast_i2c_data->slave_dma == DMA_MODE) { + i2c_dev->do_slave_xfer = ast_i2c_do_dma_xfer; +- else { +- if(i2c_dev->ast_i2c_data->request_pool_buff_page(&(i2c_dev->req_page)) == 0) ++ i2c_dev->slave_xfer_mode = DMA_XFER; ++ } else { ++ if(i2c_dev->ast_i2c_data->request_pool_buff_page(&(i2c_dev->req_page)) == 0) { + i2c_dev->do_slave_xfer = ast_i2c_do_pool_xfer; +- else ++ i2c_dev->slave_xfer_mode = BUFF_XFER; ++ } else { + i2c_dev->do_slave_xfer = ast_i2c_do_byte_xfer; ++ dev_err(i2c_dev->dev,"i2cdriver: pool request failed for slave\n"); ++ i2c_dev->slave_xfer_mode = BYTE_XFER; ++ i2c_dev->slave_xfer_len = 1; ++ } + } + + i2c_dev->do_slave_xfer(i2c_dev); +@@ -1254,6 +1291,7 @@ static void ast_i2c_slave_addr_match(struct ast_i2c_dev *i2c_dev) + static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) + { + u32 sts; ++ u32 temp; + + struct ast_i2c_dev *i2c_dev = dev_id; + u32 isr_sts = readl(i2c_dev->ast_i2c_data->reg_gr); +@@ -1280,17 +1318,15 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) + } + + if(AST_I2CD_INTR_STS_ABNORMAL & sts) { +- i2c_dev->cmd_err |= AST_I2CD_INTR_STS_ABNORMAL; +- // Turn off interrupts for further abnormal +- // conditions until we fix this one. +- ast_i2c_write(i2c_dev, +- ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) & +- ~AST_I2CD_ABNORMAL_INTR_EN, +- I2C_INTR_CTRL_REG); +- complete(&i2c_dev->cmd_complete); +- sts &= ~AST_I2CD_INTR_STS_ABNORMAL; ++ // TODO: observed abnormal interrupt happening when the bus is stressed with traffic ++ dev_err(i2c_dev->dev, "abnormal interrupt happens with status: %x, slave mode: %d\n", sts, i2c_dev->slave_operation); + // Need to clear the interrupt + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_ABNORMAL, I2C_INTR_STS_REG); ++ ++ i2c_dev->cmd_err |= AST_I2CD_INTR_STS_ABNORMAL; ++ complete(&i2c_dev->cmd_complete); ++ ++ return IRQ_HANDLED; + } + + switch(sts) { +@@ -1316,15 +1352,47 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) + ast_i2c_master_xfer_done(i2c_dev); + + } else { +- printk("ast_i2c: TX_ACK | NORMAL_STOP; xfer_last %d\n", i2c_dev->xfer_last); ++ dev_err(i2c_dev->dev,"ast_i2c: TX_ACK | NORMAL_STOP; xfer_last %d\n", i2c_dev->xfer_last); ++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_ACK | AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG); ++ uint32_t new_val = ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | ++ AST_I2CD_NORMAL_STOP_INTR_EN | ++ AST_I2CD_TX_ACK_INTR_EN; ++ ast_i2c_write(i2c_dev, new_val, I2C_INTR_CTRL_REG); ++ //take care ++ i2c_dev->cmd_err |= AST_LOCKUP_DETECTED; ++ complete(&i2c_dev->cmd_complete); ++ } ++ break; ++ case AST_I2CD_INTR_STS_TX_ACK | AST_I2CD_INTR_STS_NORMAL_STOP | AST_I2CD_INTR_STS_SLAVE_MATCH : ++ if((i2c_dev->xfer_last == 1) && (i2c_dev->slave_operation == 0)) { ++ dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_TX_ACK | AST_I2CD_INTR_STS_NORMAL_STOP | AST_I2CD_INTR_STS_SLAVE_MATCH= %x\n",sts); ++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_ACK | AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG); ++ //take care ++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | ++ AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ++ ast_i2c_master_xfer_done(i2c_dev); ++ ++ // Handle the new slave match interrupt ++ ast_i2c_slave_addr_match(i2c_dev); ++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_SLAVE_MATCH, I2C_INTR_STS_REG); ++ } else { ++ dev_err(i2c_dev->dev, "Slave TX_ACK | NORMAL_STOP | AST_I2CD_INTR_STS_SLAVE_MATCH; xfer_last %d\n", i2c_dev->xfer_last); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_ACK | AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG); + uint32_t new_val = ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | +- AST_I2CD_NORMAL_STOP_INTR_EN | ++ AST_I2CD_NORMAL_STOP_INTR_EN | + AST_I2CD_TX_ACK_INTR_EN; + ast_i2c_write(i2c_dev, new_val, I2C_INTR_CTRL_REG); + //take care + i2c_dev->cmd_err |= AST_LOCKUP_DETECTED; + complete(&i2c_dev->cmd_complete); ++ ++ // stop previous slave transaction ++ i2c_dev->slave_event = I2C_SLAVE_EVENT_STOP; ++ ast_i2c_slave_xfer_done(i2c_dev); ++ ++ // Handle the new slave match interrupt ++ ast_i2c_slave_addr_match(i2c_dev); ++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_SLAVE_MATCH, I2C_INTR_STS_REG); + } + break; + +@@ -1332,9 +1400,8 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) + if(i2c_dev->slave_operation == 1) { + i2c_dev->slave_event = I2C_SLAVE_EVENT_NACK; + ast_i2c_slave_xfer_done(i2c_dev); +- dev_dbg(i2c_dev->dev, "S clear isr: AST_I2CD_INTR_STS_TX_NAK = %x\n",sts); ++ dev_err(i2c_dev->dev, "S clear isr: AST_I2CD_INTR_STS_TX_NAK = %x\n",sts); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_NAK, I2C_INTR_STS_REG); +- + } else { + dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_TX_NAK = %x\n",sts); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_NAK, I2C_INTR_STS_REG); +@@ -1352,7 +1419,10 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) + case AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_NORMAL_STOP: + if(i2c_dev->slave_operation == 1) { + printk("SLAVE TODO .... \n"); +- ++ i2c_dev->slave_operation = 0; ++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG); ++ i2c_dev->cmd_err |= AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_NORMAL_STOP; ++ complete(&i2c_dev->cmd_complete); + } else { + dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_TX_NAK| AST_I2CD_INTR_STS_NORMAL_STOP = %x\n",sts); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG); +@@ -1365,12 +1435,17 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) + //Issue : Workaround for I2C slave mode + case AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_SLAVE_MATCH: + if(i2c_dev->slave_operation == 1) { +- i2c_dev->slave_event = I2C_SLAVE_EVENT_NACK; +- ast_i2c_slave_xfer_done(i2c_dev); ++ dev_err(i2c_dev->dev, "i2cdriver: TX_NAK and Slave match sts = %x\n",sts); + ast_i2c_slave_addr_match(i2c_dev); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_SLAVE_MATCH , I2C_INTR_STS_REG); + } else { + printk("ERROR !!!!\n"); ++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_NAK, I2C_INTR_STS_REG); ++ i2c_dev->cmd_err |= AST_I2CD_INTR_STS_TX_NAK; ++ complete(&i2c_dev->cmd_complete); ++ ++ ast_i2c_slave_addr_match(i2c_dev); ++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_SLAVE_MATCH , I2C_INTR_STS_REG); + } + break; + case AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_SLAVE_MATCH: +@@ -1378,7 +1453,17 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) + dev_dbg(i2c_dev->dev, "S clear isr: AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_SLAVE_MATCH = %x\n",sts); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_SLAVE_MATCH, I2C_INTR_STS_REG); + break; ++ case AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_SLAVE_MATCH | AST_I2CD_INTR_STS_ARBIT_LOSS: ++ dev_err(i2c_dev->dev, "M clear isr: sts = %x\n",sts); ++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_ARBIT_LOSS, I2C_INTR_STS_REG); ++ i2c_dev->cmd_err |= AST_I2CD_INTR_STS_ARBIT_LOSS; ++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | ++ AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); ++ complete(&i2c_dev->cmd_complete); + ++ ast_i2c_slave_addr_match(i2c_dev); ++ ast_i2c_write(i2c_dev, 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(i2c_dev->slave_operation == 1) { + i2c_dev->slave_event = I2C_SLAVE_EVENT_WRITE; +@@ -1389,7 +1474,6 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) + dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_RX_DOWN = %x\n",sts); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_RX_DOWN, I2C_INTR_STS_REG); + ast_i2c_master_xfer_done(i2c_dev); +- + } + break; + +@@ -1407,7 +1491,7 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) + complete(&i2c_dev->cmd_complete); + } + break; +- case (AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_NORMAL_STOP): ++ case AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_NORMAL_STOP: + /* Whether or not we're done, the hardware thinks we're done, so bail. */ + if(i2c_dev->slave_operation == 0) { + dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_NORMAL_STOP = %x\n",sts); +@@ -1416,18 +1500,47 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | + AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); + ast_i2c_master_xfer_done(i2c_dev); +- } ++ } else { ++ dev_err(i2c_dev->dev, "S clear isr: AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_NORMAL_STOP = %x\n",sts); ++ i2c_dev->slave_event = I2C_SLAVE_EVENT_STOP; ++ ast_i2c_slave_xfer_done(i2c_dev); ++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG); ++ ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | ++ AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); ++ ast_i2c_master_xfer_done(i2c_dev); ++ } + break; + case AST_I2CD_INTR_STS_ARBIT_LOSS: +- dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_ARBIT_LOSS = %x\n",sts); ++ dev_err(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_ARBIT_LOSS = %x\n",sts); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_ARBIT_LOSS, I2C_INTR_STS_REG); + i2c_dev->cmd_err |= AST_I2CD_INTR_STS_ARBIT_LOSS; + complete(&i2c_dev->cmd_complete); + break; + case AST_I2CD_INTR_STS_SCL_TO: ++ dev_err(i2c_dev->dev, "SCL LOW detected with sts = %x, slave mode: %x\n",sts, i2c_dev->slave_operation); ++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_SCL_TO, I2C_INTR_STS_REG); ++ i2c_dev->cmd_err |= AST_I2CD_INTR_STS_SCL_TO; ++ complete(&i2c_dev->cmd_complete); ++ ++ // Reset i2c controller ++ temp = ast_i2c_read(i2c_dev,I2C_FUN_CTRL_REG); ++ ++ ast_i2c_write(i2c_dev, temp & ~(AST_I2CD_SLAVE_EN | AST_I2CD_MASTER_EN), I2C_FUN_CTRL_REG); ++ ++ ast_i2c_write(i2c_dev, temp, I2C_FUN_CTRL_REG); ++ break; ++ case AST_I2CD_INTR_STS_SLAVE_MATCH | AST_I2CD_INTR_STS_SCL_TO: ++ dev_err(i2c_dev->dev, "SCL LOW detected with sts = %x, slave mode: %x\n",sts, i2c_dev->slave_operation); ++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_SCL_TO | AST_I2CD_INTR_STS_SLAVE_MATCH, I2C_INTR_STS_REG); + i2c_dev->cmd_err |= AST_I2CD_INTR_STS_SCL_TO; + complete(&i2c_dev->cmd_complete); + ++ // Reset i2c controller ++ temp = ast_i2c_read(i2c_dev,I2C_FUN_CTRL_REG); ++ ++ ast_i2c_write(i2c_dev, temp & ~(AST_I2CD_SLAVE_EN | AST_I2CD_MASTER_EN), I2C_FUN_CTRL_REG); ++ ++ ast_i2c_write(i2c_dev, temp, I2C_FUN_CTRL_REG); + break; + case AST_I2CD_INTR_STS_GCALL_ADDR: + i2c_dev->cmd_err |= AST_I2CD_INTR_STS_GCALL_ADDR; +@@ -1437,24 +1550,26 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) + 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: ++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_SDA_DL_TO, I2C_INTR_STS_REG); ++ i2c_dev->cmd_err |= AST_I2CD_INTR_STS_SDA_DL_TO; ++ complete(&i2c_dev->cmd_complete); + break; + case AST_I2CD_INTR_STS_BUS_RECOVER: +- dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_BUS_RECOVER= %x\n",sts); ++ dev_err(i2c_dev->dev, "Bus recover with sts= %x, slave mode: %x\n",sts, i2c_dev->slave_operation); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_BUS_RECOVER, I2C_INTR_STS_REG); + complete(&i2c_dev->cmd_complete); + break; + default: +- //TODO: Clearing this interrupt for now, but needs to cleanup this ISR function +- ast_i2c_write(i2c_dev, sts, I2C_INTR_STS_REG); ++ printk("GR %x : Status : %x, bus_id %d\n",i2c_dev->ast_i2c_data->reg_gr, sts, i2c_dev->bus_id); + + // Handle Arbitration Loss + if (sts & AST_I2CD_INTR_STS_ARBIT_LOSS) { ++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_ARBIT_LOSS, I2C_INTR_STS_REG); + i2c_dev->cmd_err |= AST_I2CD_INTR_STS_ARBIT_LOSS; + complete(&i2c_dev->cmd_complete); + sts &= (~AST_I2CD_INTR_STS_ARBIT_LOSS); +@@ -1462,22 +1577,35 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) + + // Handle the write transaction ACK + if (sts & AST_I2CD_INTR_STS_TX_ACK) { ++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_ACK, I2C_INTR_STS_REG); + ast_i2c_master_xfer_done(i2c_dev); +- complete(&i2c_dev->cmd_complete); + sts &= (~AST_I2CD_INTR_STS_TX_ACK); + } + ++ // Handle Normal Stop conditon ++ if (sts & AST_I2CD_INTR_STS_NORMAL_STOP) { ++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_ACK, I2C_INTR_STS_REG); ++ sts &= (~AST_I2CD_INTR_STS_NORMAL_STOP); ++ i2c_dev->cmd_err |= AST_I2CD_INTR_STS_NORMAL_STOP; ++ complete(&i2c_dev->cmd_complete); ++ } ++ + // Handle the Slave address match + if (sts & AST_I2CD_INTR_STS_SLAVE_MATCH) { + ast_i2c_slave_addr_match(i2c_dev); + sts &= (~AST_I2CD_INTR_STS_SLAVE_MATCH); ++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_SLAVE_MATCH, I2C_INTR_STS_REG); + } + ++ + // TODO: Debug print for any unhandled condition + if(sts) { + printk("GR %x : Status : %x, bus_id %d\n",i2c_dev->ast_i2c_data->reg_gr, sts, i2c_dev->bus_id); + } + ++ //TODO: Clearing this interrupt for now, but needs to cleanup this ISR function ++ ast_i2c_write(i2c_dev, sts, I2C_INTR_STS_REG); ++ + return IRQ_HANDLED; + } + +@@ -1492,16 +1620,25 @@ static int ast_i2c_do_msgs_xfer(struct ast_i2c_dev *i2c_dev, struct i2c_msg *msg + + spin_lock_irqsave(&i2c_dev->master_lock, flags); + +- //request +- if(i2c_dev->ast_i2c_data->master_dma == BYTE_MODE) ++ //request: update master_xfer_mode based on master_dma selection ++ if(i2c_dev->ast_i2c_data->master_dma == BYTE_MODE) { + i2c_dev->do_master_xfer = ast_i2c_do_byte_xfer; +- else if (i2c_dev->ast_i2c_data->master_dma == DMA_MODE) ++ i2c_dev->master_xfer_mode = BYTE_XFER; ++ i2c_dev->master_xfer_len = 1; ++ } else if (i2c_dev->ast_i2c_data->master_dma == DMA_MODE) { + i2c_dev->do_master_xfer = ast_i2c_do_dma_xfer; +- else { +- if(i2c_dev->ast_i2c_data->request_pool_buff_page(&(i2c_dev->req_page)) == 0) ++ i2c_dev->master_xfer_mode = DMA_XFER; ++ } else { ++ if(i2c_dev->ast_i2c_data->request_pool_buff_page(&(i2c_dev->req_page)) == 0) { + i2c_dev->do_master_xfer = ast_i2c_do_pool_xfer; +- else ++ i2c_dev->master_xfer_mode = BUFF_XFER; ++ } else { + i2c_dev->do_master_xfer = ast_i2c_do_byte_xfer; ++ dev_err(i2c_dev->dev, "i2cdriver: pool request failed for master\n"); ++ i2c_dev->master_xfer_mode = BYTE_XFER; ++ i2c_dev->master_xfer_len = 1; ++ ++ } + } + + // printk("start xfer ret = %d \n",ret); +@@ -1534,7 +1671,7 @@ static int ast_i2c_do_msgs_xfer(struct ast_i2c_dev *i2c_dev, struct i2c_msg *msg + i2c_dev->master_msgs = NULL; + + if (ret == 0) { +- dev_dbg(i2c_dev->dev, "controller timed out\n"); ++ dev_err(i2c_dev->dev, "controller timed out\n"); + i2c_dev->state = (ast_i2c_read(i2c_dev,I2C_CMD_REG) >> 19) & 0xf; + // printk("sts [%x], isr sts [%x] \n",i2c_dev->state, ast_i2c_read(i2c_dev,I2C_INTR_STS_REG)); + ret = -ETIMEDOUT; +@@ -1564,9 +1701,10 @@ static int ast_i2c_do_msgs_xfer(struct ast_i2c_dev *i2c_dev, struct i2c_msg *msg + + } + stop: +- init_completion(&i2c_dev->cmd_complete); + if(i2c_dev->cmd_err & AST_I2CD_INTR_STS_NORMAL_STOP) + goto out; ++ init_completion(&i2c_dev->cmd_complete); ++ i2c_dev->cmd_err = 0; + ast_i2c_write(i2c_dev, AST_I2CD_M_STOP_CMD, I2C_CMD_REG); + wait_for_completion_interruptible_timeout(&i2c_dev->cmd_complete, + i2c_dev->adap.timeout*HZ); +@@ -1605,7 +1743,7 @@ static int ast_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) + ret = ast_i2c_do_msgs_xfer(i2c_dev, msgs, num); + if (ret != -EAGAIN) + goto out; +- dev_dbg(&adap->dev, "Retrying transmission [%d]\n",i); ++ dev_dbg(&i2c_dev->adap.dev, "Retrying transmission [%d]\n",i); + udelay(100); + } + +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/net/ftgmac100_26.c b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/net/ftgmac100_26.c +index 3a5d796..f558d38 100644 +--- a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/net/ftgmac100_26.c ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/net/ftgmac100_26.c +@@ -901,6 +901,41 @@ void Enable_Broadcast_Filter (struct net_device * dev) + lp->Retry = 0; + } + ++void Disable_Multicast_Filter (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = DISABLE_GLOBAL_MULTICAST_FILTERING; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = 0; ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (DISABLE_GLOBAL_MULTICAST_FILTERING | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ } ++ else { ++ lp->Retry = 0; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++} ++ + void Disable_VLAN (struct net_device * dev) + { + struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; +@@ -1416,6 +1451,8 @@ static void ftgmac100_enable( struct net_device *dev ) + Enable_Set_MAC_Address(dev); + //Enable Broadcast Filter + Enable_Broadcast_Filter(dev); ++//Disable Multicast Filter ++ Disable_Multicast_Filter(dev); + //Disable VLAN + Disable_VLAN(dev); + //Enable AEN +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/serial/8250.c b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/serial/8250.c +index f16da59..d01c1c7 100644 +--- a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/serial/8250.c ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/serial/8250.c +@@ -127,6 +127,11 @@ static unsigned long probe_rsa[PORT_RSA_MAX]; + static unsigned int probe_rsa_count; + #endif /* CONFIG_SERIAL_8250_RSA */ + ++struct rs485_wait_state { ++ int gpio; ++ int waiting; ++}; ++ + struct uart_8250_port { + struct uart_port port; + struct timer_list timer; /* "no irq" timer */ +@@ -156,6 +161,8 @@ struct uart_8250_port { + */ + void (*pm)(struct uart_port *port, + unsigned int state, unsigned int old); ++ ++ struct rs485_wait_state rs485_wait_state; + }; + + struct irq_info { +@@ -169,6 +176,9 @@ struct irq_info { + static struct hlist_head irq_lists[NR_IRQ_HASH]; + static DEFINE_MUTEX(hash_mutex); /* Used to walk the hash */ + ++#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) ++static void wait_for_xmitr(struct uart_8250_port *up, int bits); ++ + /* + * Here we define the default xmit fifo size used for each type of UART. + */ +@@ -530,6 +540,31 @@ static void serial_dl_write(struct uart_8250_port *up, int value) + #define serial_dl_write(up, value) _serial_dl_write(up, value) + #endif + ++// unfortunately it seems the gpio switch for RS485 can be late even with the ++// wait queue based wakeup of the task waiting on its completion, so we *have* ++// to do the gpio switch in the interrupt handler. ++static void rs485_wait_end(struct uart_8250_port *up) { ++ struct rs485_wait_state *rs485_wait_state = ++ &up->rs485_wait_state; ++ if (rs485_wait_state->waiting) { ++ int status; ++ status = serial_in(up, UART_LSR); ++ // no interrupt will be fire for shift register (TEMT) so we have to spin ++ // on it. ++ if (status & UART_LSR_THRE) { ++ wait_for_xmitr(up, BOTH_EMPTY); ++ // turn off RS485 DE pin ++ if (rs485_wait_state->gpio) ++ gpio_set_value(rs485_wait_state->gpio, 0); ++ // grab any phantom char seen on RX when transceiver switches ++ (void) serial_inp(up, UART_RX); ++ // enable read ++ up->port.ignore_status_mask &= ~UART_LSR_DR; ++ rs485_wait_state->waiting = 0; ++ } ++ } ++} ++ + /* + * For the 16C950 + */ +@@ -1235,6 +1270,7 @@ static inline void __stop_tx(struct uart_8250_port *p) + p->ier &= ~UART_IER_THRI; + serial_out(p, UART_IER, p->ier); + } ++ uart_write_wakeup(&p->port); + } + + static void serial8250_stop_tx(struct uart_port *port) +@@ -1436,7 +1472,7 @@ static unsigned int check_modem_status(struct uart_8250_port *up) + if (status & UART_MSR_DCTS) + uart_handle_cts_change(&up->port, status & UART_MSR_CTS); + +- wake_up_interruptible(&up->port.info->delta_msr_wait); ++ wake_up_interruptible(&up->port.info->delta_msr_wait); + } + + return status; +@@ -1462,6 +1498,7 @@ static void serial8250_handle_port(struct uart_8250_port *up) + if (status & UART_LSR_THRE) + transmit_chars(up); + ++ rs485_wait_end(up); + spin_unlock_irqrestore(&up->port.lock, flags); + } + +@@ -1777,8 +1814,6 @@ static void serial8250_break_ctl(struct uart_port *port, int break_state) + spin_unlock_irqrestore(&up->port.lock, flags); + } + +-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) +- + /* + * Wait for transmitter & holding register to empty + */ +@@ -2539,8 +2574,13 @@ static int serial8250_ioctl(struct uart_port *port, unsigned int cmd, unsigned l + int ret = -ENOIOCTLCMD; + // kernel-space RS485 drain-and-switch hack + if (cmd == TIOCSERWAITTEMT) { +- // wait for kernel buffers and UART FIFO to both empty + struct circ_buf *xmit = &up->port.info->xmit; ++ spin_lock_irqsave(&up->port.lock, flags); ++ up->rs485_wait_state.gpio = arg; ++ up->rs485_wait_state.waiting = 1; ++ spin_unlock_irqrestore(&up->port.lock, flags); ++ ++ // wait for kernel buffers and UART FIFO to both empty + wait_event_interruptible( + thre_wait, + uart_circ_empty(xmit) && +@@ -2548,14 +2588,6 @@ static int serial8250_ioctl(struct uart_port *port, unsigned int cmd, unsigned l + // spin until TEMT (transmit shift register empty) + spin_lock_irqsave(&up->port.lock, flags); + wait_for_xmitr(up, BOTH_EMPTY); +- if (arg != 0) { +- // turn off RS485 DE pin +- gpio_set_value(arg, 0); +- } +- // grab any phantom char seen on RX when transceiver switches +- (void) serial_inp(up, UART_RX); +- // enable read +- up->port.ignore_status_mask &= ~UART_LSR_DR; + spin_unlock_irqrestore(&up->port.lock, flags); + return 0; + } +@@ -2607,6 +2639,8 @@ static void __init serial8250_isa_init_ports(void) + + init_timer(&up->timer); + up->timer.function = serial8250_timeout; ++ up->rs485_wait_state.waiting = 0; ++ up->rs485_wait_state.gpio = 0; + + /* + * ALPHA_KLUDGE_MCR needs to be killed. +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/usb/gadget/aspeed_udc.c b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/usb/gadget/aspeed_udc.c +index a65e52a..51cb34c 100644 +--- a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/usb/gadget/aspeed_udc.c ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/usb/gadget/aspeed_udc.c +@@ -580,10 +580,10 @@ static void ep_dequeue_locked(struct ast_ep* ep, struct ast_usb_request *req) { + + static void ep_dequeue_all(struct ast_ep* ep, int status) { + struct ast_usb_request *req; +- struct ast_usb_request *n; + unsigned long flags; + spin_lock_irqsave(&ep->lock, flags); +- list_for_each_entry_safe(req, n, &ep->queue, queue) { ++ while (!list_empty(&ep->queue)) { ++ req = list_entry(ep->queue.next, struct ast_usb_request, queue); + ep_dequeue_locked(ep, req); + req->req.status = status; + if(req->req.complete) { +@@ -654,8 +654,14 @@ static void ep_txrx_check_done(struct ast_ep* ep) { + spin_lock_irqsave(&ep->lock, flags); + status = ep_hreadl(ep, DESC_STATUS); + // if txrx complete; +- if(!(status & 0xff) && +- !list_empty(&ep->queue)) { ++ if (!(status & 0xff)) { ++ /* DMA is done */ ++ ep->dma_busy = 0; ++ /* if the list is empty, nothing to do */ ++ if (list_empty(&ep->queue)) { ++ spin_unlock_irqrestore(&ep->lock, flags); ++ return; ++ } + req = list_entry(ep->queue.next, struct ast_usb_request, queue); + if(!req->in_transit) { + spin_unlock_irqrestore(&ep->lock, flags); +@@ -663,7 +669,6 @@ static void ep_txrx_check_done(struct ast_ep* ep) { + } + //head rq completed + req->in_transit = 0; +- ep->dma_busy = 0; + if(!ep->to_host) { + req->lastpacket = (status >> 16) & 0x3ff; + __cpuc_flush_kern_all(); +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/watchdog/ast_wdt.c b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/watchdog/ast_wdt.c +index e599a55..cfe70a1 100644 +--- a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/watchdog/ast_wdt.c ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/watchdog/ast_wdt.c +@@ -450,7 +450,7 @@ static int ast_wdt_open(struct inode *inode, struct file *file) + + static int ast_wdt_release(struct inode *inode, struct file *file) + { +- if (expect_close != 42 || !nowayout) ++ if (expect_close != 42 && !nowayout) + { + /* handles the case where the device is closed without the "magic + * close" character (anything that is not 'V' qualifies -- see the diff --git a/meta-aspeed/recipes-kernel/linux/linux-aspeed.inc b/meta-aspeed/recipes-kernel/linux/linux-aspeed.inc index a66c7e1..5e28e76 100644 --- a/meta-aspeed/recipes-kernel/linux/linux-aspeed.inc +++ b/meta-aspeed/recipes-kernel/linux/linux-aspeed.inc @@ -11,16 +11,22 @@ do_compile[depends] = "libgcc:do_populate_sysroot" inherit kernel # auto load the following modules -module_autoload_tun = "tun" -module_autoload_at24 = "at24" -module_autoload_ads7828 = "ads7828" -module_autoload_pcf8574 = "pcf8574" -module_autoload_max127 = "max127" +KERNEL_MODULE_AUTOLOAD += " \ + adm1275 \ + ads7828 \ + at24 \ + fb_panther_plus \ + max127 \ + pcf8574 \ + pfe1100 \ + pmbus_core \ + tun \ +" + +KERNEL_MODULE_PROBECONF += " \ + max127 \ +" module_conf_max127 = "options max127 scaling=24414" -module_autoload_pmbus_core = "pmbus_core" -module_autoload_pfe1100 = "pfe1100" -module_autoload_fb_panther_plus = "fb_panther_plus" -module_autoload_adm1275 = "adm1275" # Do not install kernel in rootfs do_install[postfuncs] += "remove_kernel_image_from_rootfs" diff --git a/meta-aspeed/recipes-kernel/linux/linux-aspeed_2.6.28.9.bb b/meta-aspeed/recipes-kernel/linux/linux-aspeed_2.6.28.9.bb index 9a76066..7798bab 100644 --- a/meta-aspeed/recipes-kernel/linux/linux-aspeed_2.6.28.9.bb +++ b/meta-aspeed/recipes-kernel/linux/linux-aspeed_2.6.28.9.bb @@ -3,7 +3,7 @@ SRCREV = "1e85856853e24e9013d142adaad38c2adc7e48ac" SRC_URI = "git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git;protocol=https;branch=linux-2.6.28.y \ - file://patch-2.6.28.9/0000-linux-aspeed-064.patch \ + file://patch-2.6.28.9/0000-linux-aspeed-064.patch;striplevel=1 \ file://patch-2.6.28.9/0000-linux-openbmc.patch \ file://patch-2.6.28.9/0001-MTD-fix-m25p80-64-bit-divisions.patch \ file://patch-2.6.28.9/0005-mtd-Bug-in-m25p80.c-during-whole-chip-erase.patch \ @@ -23,28 +23,37 @@ SRC_URI = "git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git file://patch-2.6.28.9/0001-bzip2-lzma-library-support-for-gzip-bzip2-and-lzma-d.patch \ file://patch-2.6.28.9/0002-bzip2-lzma-config-and-initramfs-support-for-bzip2-lz.patch \ file://patch-2.6.28.9/0032-Create-snapshot-of-OpenBMC.patch \ + file://patch-2.6.28.9/0033-Linux-snapshot-of-OpenBMC-f926614.patch;striplevel=6 \ " -S = "${WORKDIR}/git" - LINUX_VERSION ?= "2.6.28.9" LINUX_VERSION_EXTENSION ?= "-aspeed" PR = "r1" PV = "${LINUX_VERSION}" +include linux-aspeed.inc + +S = "${WORKDIR}/git" + # Install bounds.h for external module install # The default install script handles this. However, it looks for bounds.h from # 'include/generated', which doesnot match 2.6.28, where the file is in # 'include/linux'. -do_install[postfuncs] += "install_bounds_h" -install_bounds_h() { - kerneldir=${D}${KERNEL_SRC_PATH} - if [ -f include/linux/bounds.h ]; then - cp -l include/linux/bounds.h $kerneldir/include/linux/bounds.h - fi +addtask create_generated after do_compile before do_shared_workdir +do_create_generated() { + install -d ${B}/include/generated + cp -l ${B}/include/linux/bounds.h ${B}/include/generated/bounds.h } -KERNEL_CONFIG_COMMAND = "oe_runmake wedge_defconfig && oe_runmake oldconfig" +# With Fido, ${KERNEL_SRC} is set to ${STAGING_KERENL_DIR}, which is passed +# to kernel module build. So, copy all .h files from the build direcory to +# the ${STAGING_KERNEL_DIR} +addtask copy_to_kernelsrc after do_shared_workdir before do_compile_kernelmodules +do_copy_to_kernelsrc() { + kerneldir=${STAGING_KERNEL_DIR}/include/linux + install -d ${kerneldir} + cp -l ${B}/include/linux/* ${kerneldir}/ +} -include linux-aspeed.inc +KERNEL_CC += " --sysroot=${PKG_CONFIG_SYSROOT_DIR}" |