summaryrefslogtreecommitdiffstats
path: root/meta-aspeed/recipes-kernel
diff options
context:
space:
mode:
authorTian Fang <tfang@fb.com>2015-12-14 22:08:40 -0800
committerTian Fang <tfang@fb.com>2015-12-15 09:49:21 -0800
commite65a7944211c70f6b5cfb6cedd73cc31105319de (patch)
tree067082251bc52bc6c09ca87feaa1352d0468a5ac /meta-aspeed/recipes-kernel
parent8a67fbdd0e251bb34d55992b0771edba1837d589 (diff)
downloadast2050-yocto-openbmc-e65a7944211c70f6b5cfb6cedd73cc31105319de.zip
ast2050-yocto-openbmc-e65a7944211c70f6b5cfb6cedd73cc31105319de.tar.gz
Sync to internal OpenBMC repo f926614
Diffstat (limited to 'meta-aspeed/recipes-kernel')
-rw-r--r--meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0033-Linux-snapshot-of-OpenBMC-f926614.patch978
-rw-r--r--meta-aspeed/recipes-kernel/linux/linux-aspeed.inc24
-rw-r--r--meta-aspeed/recipes-kernel/linux/linux-aspeed_2.6.28.9.bb31
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}"
OpenPOWER on IntegriCloud