summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTian Fang <tfang@fb.com>2016-04-13 01:49:31 +0100
committerJavier Jardón <jjardon@gnome.org>2016-04-13 01:50:31 +0100
commit3842b07578ca8c7473e5d96e0bd2000629540426 (patch)
tree9df2e875b6355b1d7f32a33a00797785a85584d7
parent1812494d7169dd66ffd0a70132361416f4005963 (diff)
downloadlinux-stable-3842b07578ca8c7473e5d96e0bd2000629540426.tar.gz
Linux snapshot of OpenBMC f926614
-rw-r--r--arch/arm/plat-aspeed/dev-i2c.c9
-rw-r--r--drivers/hwmon/ast_adc.c2
-rw-r--r--drivers/i2c/busses/i2c-ast.c296
-rw-r--r--drivers/net/ftgmac100_26.c37
-rw-r--r--drivers/serial/8250.c58
-rw-r--r--drivers/usb/gadget/aspeed_udc.c15
-rw-r--r--drivers/watchdog/ast_wdt.c2
7 files changed, 321 insertions, 98 deletions
diff --git a/arch/arm/plat-aspeed/dev-i2c.c b/arch/arm/plat-aspeed/dev-i2c.c
index fffa4803e70f..a6f75b108f19 100644
--- a/arch/arm/plat-aspeed/dev-i2c.c
+++ b/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/drivers/hwmon/ast_adc.c b/drivers/hwmon/ast_adc.c
index 8f5aa541d12d..e21d52eeae4a 100644
--- a/drivers/hwmon/ast_adc.c
+++ b/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/drivers/i2c/busses/i2c-ast.c b/drivers/i2c/busses/i2c-ast.c
index 9bb3154e6bd8..48f019278907 100644
--- a/drivers/i2c/busses/i2c-ast.c
+++ b/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/drivers/net/ftgmac100_26.c b/drivers/net/ftgmac100_26.c
index 3a5d7969278a..f558d385e8dc 100644
--- a/drivers/net/ftgmac100_26.c
+++ b/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/drivers/serial/8250.c b/drivers/serial/8250.c
index f16da5982358..d01c1c7152e2 100644
--- a/drivers/serial/8250.c
+++ b/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/drivers/usb/gadget/aspeed_udc.c b/drivers/usb/gadget/aspeed_udc.c
index a65e52a0af62..51cb34ca65c5 100644
--- a/drivers/usb/gadget/aspeed_udc.c
+++ b/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/drivers/watchdog/ast_wdt.c b/drivers/watchdog/ast_wdt.c
index e599a557076f..cfe70a15587a 100644
--- a/drivers/watchdog/ast_wdt.c
+++ b/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