From 34aeb43e2d3800f4d8f96feb9f1b49cd506679d5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 10 Feb 2009 09:04:00 +0000 Subject: serial: sh-sci: fix overrun error handling for SH7785 SCIF. There was a typo for the overrun bit definition, causing it not to be handled correctly on SH7785, fix it up. Signed-off-by: Kuninori Morimoto Signed-off-by: Paul Mundt --- drivers/serial/sh-sci.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/serial') diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index 3599828b9766..022e89ffec1d 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h @@ -133,7 +133,7 @@ # define SCSPTR3 0xffed0024 /* 16 bit SCIF */ # define SCSPTR4 0xffee0024 /* 16 bit SCIF */ # define SCSPTR5 0xffef0024 /* 16 bit SCIF */ -# define SCIF_OPER 0x0001 /* Overrun error bit */ +# define SCIF_ORER 0x0001 /* Overrun error bit */ # define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ #elif defined(CONFIG_CPU_SUBTYPE_SH7201) || \ defined(CONFIG_CPU_SUBTYPE_SH7203) || \ -- cgit v1.2.3 From 27c0c8e511fa9e2389503926840fac606d90a049 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Wed, 18 Feb 2009 14:48:28 -0800 Subject: atmel_serial might lose modem status change I found a problem of handling of modem status of atmel_serial driver. With the commit 1ecc26 ("atmel_serial: split the interrupt handler"), handling of modem status signal was splitted into two parts. The atmel_tasklet_func() compares new status with irq_status_prev, but irq_status_prev is not correct if signal status was changed while the port is closed. Here is a sequence to cause problem: 1. Remote side sets CTS (and DSR). 2. Local side close the port. 3. Local side clears RTS and DTR. 4. Remote side clears CTS and DSR. 5. Local side reopen the port. hw_stopped becomes 1. 6. Local side sets RTS and DTR. 7. Remote side sets CTS and DSR. Then CTS change interrupt can be received, but since CTS bit in irq_status_prev and new status is same, uart_handle_cts_change() will not be called (so hw_stopped will not be cleared, i.e. cannot send any data). I suppose irq_status_prev should be initialized at somewhere in open sequence. Itai Levi pointed out that we need to initialize atmel_port->irq_status as well here. His analysis is as follows: > Regarding the second part of the patch (which resets irq_status_prev), > it turns out that both versions of the patch (mine and Atsushi's) > still leave enough room for faulty behavior when opening the port. > > This is because we are not resetting both irq_status_prev and > irq_status in atmel_startup() to CSR, which leads faulty behavior in > the following sequences: > > First case: > 1. closing the port while CTS line = 1 (TX not allowed) > 2. setting CTS line = 0 (TX allowed) > 3. opening the port > 4. transmitting one char > 5. Cannot transmit more chars, although CTS line is 0 > > Second case: > 1. closing the port while CTS line = 0 (TX allowed) > 2. setting CTS line = 1 (TX not allowed) > 3. opening the port > 4. receiving some chars > 5. Now we can transmit, although CTS line is 1 > > This reason for this is that the tasklet is scheduled as a result of > TX or RX interrupts (not a status change!), in steps 4 above. Inside > the tasklet, the atmel_port->irq_status (which holds the value from > the previous session) is compared to atmel_port->irq_status_prev. > Hence, a status-change of the CTS line is faultily detected. > > Both cases were verified on 9260 hardware. [haavard.skinnemoen@atmel.com: folded with patch from Itai Levi] Signed-off-by: Atsushi Nemoto Signed-off-by: Haavard Skinnemoen Cc: Remy Bohmer Cc: Marc Pignat Cc: Itai Levi Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/serial/atmel_serial.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/serial') diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index 89362d733d62..8f58f7ff0dd7 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c @@ -877,6 +877,10 @@ static int atmel_startup(struct uart_port *port) } } + /* Save current CSR for comparison in atmel_tasklet_func() */ + atmel_port->irq_status_prev = UART_GET_CSR(port); + atmel_port->irq_status = atmel_port->irq_status_prev; + /* * Finally, enable the serial port */ -- cgit v1.2.3 From ffa7525c13eb3db0fd19a3e1cffe2ce6f561f5f3 Mon Sep 17 00:00:00 2001 From: Adam Lackorzynski Date: Wed, 18 Feb 2009 14:48:34 -0800 Subject: jsm: additional device support I have a Digi Neo 8 PCI card (114f:00b1) Serial controller: Digi International Digi Neo 8 (rev 05) that works with the jsm driver after using the following patch. Signed-off-by: Adam Lackorzynski Cc: Scott H Kilau Cc: Wendy Xiong Acked-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/serial/jsm/jsm_driver.c | 3 +++ include/linux/pci_ids.h | 1 + 2 files changed, 4 insertions(+) (limited to 'drivers/serial') diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c index 92187e28608a..ac79cbe4c2cf 100644 --- a/drivers/serial/jsm/jsm_driver.c +++ b/drivers/serial/jsm/jsm_driver.c @@ -84,6 +84,8 @@ static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent) brd->pci_dev = pdev; if (pdev->device == PCIE_DEVICE_ID_NEO_4_IBM) brd->maxports = 4; + else if (pdev->device == PCI_DEVICE_ID_DIGI_NEO_8) + brd->maxports = 8; else brd->maxports = 2; @@ -212,6 +214,7 @@ static struct pci_device_id jsm_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2RJ45), 0, 0, 2 }, { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2RJ45PRI), 0, 0, 3 }, { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_4_IBM), 0, 0, 4 }, + { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_NEO_8), 0, 0, 5 }, { 0, } }; MODULE_DEVICE_TABLE(pci, jsm_pci_tbl); diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 918391b4b109..114b8192eab9 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1445,6 +1445,7 @@ #define PCI_DEVICE_ID_DIGI_DF_M_E 0x0071 #define PCI_DEVICE_ID_DIGI_DF_M_IOM2_A 0x0072 #define PCI_DEVICE_ID_DIGI_DF_M_A 0x0073 +#define PCI_DEVICE_ID_DIGI_NEO_8 0x00B1 #define PCI_DEVICE_ID_NEO_2DB9 0x00C8 #define PCI_DEVICE_ID_NEO_2DB9PRI 0x00C9 #define PCI_DEVICE_ID_NEO_2RJ45 0x00CA -- cgit v1.2.3 From b6adea334c6c89d5e6c94f9196bbf3a279cb53bd Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 20 Feb 2009 15:38:52 -0800 Subject: 8250: fix boot hang with serial console when using with Serial Over Lan port Intel 8257x Ethernet boards have a feature called Serial Over Lan. This feature works by emulating a serial port, and it is detected by kernel as a normal 8250 port. However, this emulation is not perfect, as also noticed on changeset 7500b1f602aad75901774a67a687ee985d85893f. Before this patch, the kernel were trying to check if the serial TX is capable of work using IRQ's. This were done with a code similar this: serial_outp(up, UART_IER, UART_IER_THRI); lsr = serial_in(up, UART_LSR); iir = serial_in(up, UART_IIR); serial_outp(up, UART_IER, 0); if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) up->bugs |= UART_BUG_TXEN; This works fine for other 8250 ports, but, on 8250-emulated SoL port, the chip is a little lazy to down UART_IIR_NO_INT at UART_IIR register. Due to that, UART_BUG_TXEN is sometimes enabled. However, as TX IRQ keeps working, and the TX polling is now enabled, the driver miss-interprets the IRQ received later, hanging up the machine until a key is pressed at the serial console. This is the 6 version of this patch. Previous versions were trying to introduce a large enough delay between serial_outp and serial_in(up, UART_IIR), but not taking forever. However, the needed delay couldn't be safely determined. At the experimental tests, a delay of 1us solves most of the cases, but still hangs sometimes. Increasing the delay to 5us was better, but still doesn't solve. A very high delay of 50 ms seemed to work every time. However, poking around with delays and pray for it to be enough doesn't seem to be a good approach, even for a quirk. So, instead of playing with random large arbitrary delays, let's just disable UART_BUG_TXEN for all SoL ports. [akpm@linux-foundation.org: fix warnings] Signed-off-by: Mauro Carvalho Chehab Cc: Alan Cox Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/serial/8250.c | 15 +++++++++++++++ drivers/serial/8250_pci.c | 36 ++++++++++++++++++++++++++++++++++++ include/linux/pci_ids.h | 3 +++ include/linux/serial_core.h | 1 + 4 files changed, 55 insertions(+) (limited to 'drivers/serial') diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 0d934bfbdd9b..b4b39811b445 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -2083,6 +2083,20 @@ static int serial8250_startup(struct uart_port *port) serial8250_set_mctrl(&up->port, up->port.mctrl); + /* Serial over Lan (SoL) hack: + Intel 8257x Gigabit ethernet chips have a + 16550 emulation, to be used for Serial Over Lan. + Those chips take a longer time than a normal + serial device to signalize that a transmission + data was queued. Due to that, the above test generally + fails. One solution would be to delay the reading of + iir. However, this is not reliable, since the timeout + is variable. So, let's just don't test if we receive + TX irq. This way, we'll never enable UART_BUG_TXEN. + */ + if (up->port.flags & UPF_NO_TXEN_TEST) + goto dont_test_tx_en; + /* * Do a quick test to see if we receive an * interrupt when we enable the TX irq. @@ -2102,6 +2116,7 @@ static int serial8250_startup(struct uart_port *port) up->bugs &= ~UART_BUG_TXEN; } +dont_test_tx_en: spin_unlock_irqrestore(&up->port.lock, flags); /* diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c index 536d8e510f66..533f82025adf 100644 --- a/drivers/serial/8250_pci.c +++ b/drivers/serial/8250_pci.c @@ -798,6 +798,21 @@ pci_default_setup(struct serial_private *priv, return setup_port(priv, port, bar, offset, board->reg_shift); } +static int skip_tx_en_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_port *port, int idx) +{ + port->flags |= UPF_NO_TXEN_TEST; + printk(KERN_DEBUG "serial8250: skipping TxEn test for device " + "[%04x:%04x] subsystem [%04x:%04x]\n", + priv->dev->vendor, + priv->dev->device, + priv->dev->subsystem_vendor, + priv->dev->subsystem_device); + + return pci_default_setup(priv, board, port, idx); +} + /* This should be in linux/pci_ids.h */ #define PCI_VENDOR_ID_SBSMODULARIO 0x124B #define PCI_SUBVENDOR_ID_SBSMODULARIO 0x124B @@ -864,6 +879,27 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { .init = pci_inteli960ni_init, .setup = pci_default_setup, }, + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_8257X_SOL, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = skip_tx_en_setup, + }, + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82573L_SOL, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = skip_tx_en_setup, + }, + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82573E_SOL, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = skip_tx_en_setup, + }, /* * ITE */ diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 114b8192eab9..aca8c458aa8a 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2323,6 +2323,9 @@ #define PCI_DEVICE_ID_INTEL_82378 0x0484 #define PCI_DEVICE_ID_INTEL_I960 0x0960 #define PCI_DEVICE_ID_INTEL_I960RM 0x0962 +#define PCI_DEVICE_ID_INTEL_8257X_SOL 0x1062 +#define PCI_DEVICE_ID_INTEL_82573E_SOL 0x1085 +#define PCI_DEVICE_ID_INTEL_82573L_SOL 0x108F #define PCI_DEVICE_ID_INTEL_82815_MC 0x1130 #define PCI_DEVICE_ID_INTEL_82815_CGC 0x1132 #define PCI_DEVICE_ID_INTEL_82092AA_0 0x1221 diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 90bbbf0b1161..df9245c7bd3b 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -296,6 +296,7 @@ struct uart_port { #define UPF_HARDPPS_CD ((__force upf_t) (1 << 11)) #define UPF_LOW_LATENCY ((__force upf_t) (1 << 13)) #define UPF_BUGGY_UART ((__force upf_t) (1 << 14)) +#define UPF_NO_TXEN_TEST ((__force upf_t) (1 << 15)) #define UPF_MAGIC_MULTIPLIER ((__force upf_t) (1 << 16)) #define UPF_CONS_FLOW ((__force upf_t) (1 << 23)) #define UPF_SHARE_IRQ ((__force upf_t) (1 << 24)) -- cgit v1.2.3 From e65fb0099fe4fe82d59ffe84f1e88a489218d7f9 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 16 Feb 2009 14:29:10 +0100 Subject: [ARM] MXC: remove _clk suffix from clock names The context makes it clear already that these are clocks, so there's no need for such a suffix. This patch only changes the clocks actually used in the tree. The remaining clocks are renamed in the subsequent architecture specific patches. Signed-off-by: Sascha Hauer --- arch/arm/mach-mx1/clock.c | 4 ++-- arch/arm/mach-mx2/clock_imx27.c | 18 +++++++++--------- arch/arm/mach-mx3/clock.c | 14 +++++++------- arch/arm/plat-mxc/dma-mx1-mx2.c | 2 +- drivers/mtd/nand/mxc_nand.c | 2 +- drivers/serial/imx.c | 2 +- drivers/w1/masters/mxc_w1.c | 2 +- 7 files changed, 22 insertions(+), 22 deletions(-) (limited to 'drivers/serial') diff --git a/arch/arm/mach-mx1/clock.c b/arch/arm/mach-mx1/clock.c index 40a2274380a3..0d0f306851d0 100644 --- a/arch/arm/mach-mx1/clock.c +++ b/arch/arm/mach-mx1/clock.c @@ -462,7 +462,7 @@ static struct clk clko_clk = { }; static struct clk dma_clk = { - .name = "dma_clk", + .name = "dma", .parent = &hclk, .round_rate = _clk_parent_round_rate, .set_rate = _clk_parent_set_rate, @@ -513,7 +513,7 @@ static struct clk gpt_clk = { }; static struct clk uart_clk = { - .name = "uart_clk", + .name = "uart", .parent = &perclk[0], .round_rate = _clk_parent_round_rate, .set_rate = _clk_parent_set_rate, diff --git a/arch/arm/mach-mx2/clock_imx27.c b/arch/arm/mach-mx2/clock_imx27.c index 7b2c1122d9ab..700a22f5ae88 100644 --- a/arch/arm/mach-mx2/clock_imx27.c +++ b/arch/arm/mach-mx2/clock_imx27.c @@ -685,7 +685,7 @@ static struct clk per_clk[] = { struct clk uart1_clk[] = { { - .name = "uart_clk", + .name = "uart", .id = 0, .parent = &per_clk[0], .secondary = &uart1_clk[1], @@ -702,7 +702,7 @@ struct clk uart1_clk[] = { struct clk uart2_clk[] = { { - .name = "uart_clk", + .name = "uart", .id = 1, .parent = &per_clk[0], .secondary = &uart2_clk[1], @@ -719,7 +719,7 @@ struct clk uart2_clk[] = { struct clk uart3_clk[] = { { - .name = "uart_clk", + .name = "uart", .id = 2, .parent = &per_clk[0], .secondary = &uart3_clk[1], @@ -736,7 +736,7 @@ struct clk uart3_clk[] = { struct clk uart4_clk[] = { { - .name = "uart_clk", + .name = "uart", .id = 3, .parent = &per_clk[0], .secondary = &uart4_clk[1], @@ -753,7 +753,7 @@ struct clk uart4_clk[] = { struct clk uart5_clk[] = { { - .name = "uart_clk", + .name = "uart", .id = 4, .parent = &per_clk[0], .secondary = &uart5_clk[1], @@ -770,7 +770,7 @@ struct clk uart5_clk[] = { struct clk uart6_clk[] = { { - .name = "uart_clk", + .name = "uart", .id = 5, .parent = &per_clk[0], .secondary = &uart6_clk[1], @@ -1110,7 +1110,7 @@ static struct clk ssi2_clk[] = { }; static struct clk nfc_clk = { - .name = "nfc_clk", + .name = "nfc", .parent = &cpu_clk, .get_rate = _clk_nfc_recalc, .enable = _clk_enable, @@ -1128,7 +1128,7 @@ static struct clk vpu_clk = { }; static struct clk dma_clk = { - .name = "dma_clk", + .name = "dma", .parent = &ahb_clk, .enable = _clk_dma_enable, .disable = _clk_dma_disable, @@ -1260,7 +1260,7 @@ static struct clk kpp_clk = { }; static struct clk owire_clk = { - .name = "owire_clk", + .name = "owire", .parent = &ipg_clk, .enable = _clk_enable, .enable_reg = CCM_PCCR0, diff --git a/arch/arm/mach-mx3/clock.c b/arch/arm/mach-mx3/clock.c index 8b41facb391b..bc3a3beb9a66 100644 --- a/arch/arm/mach-mx3/clock.c +++ b/arch/arm/mach-mx3/clock.c @@ -593,7 +593,7 @@ static struct clk epit_clk[] = { }; static struct clk nfc_clk = { - .name = "nfc_clk", + .name = "nfc", .parent = &ahb_clk, .get_rate = _clk_nfc_get_rate, }; @@ -667,7 +667,7 @@ static struct clk csi_clk = { static struct clk uart_clk[] = { { - .name = "uart_clk", + .name = "uart", .id = 0, .parent = &perclk_clk, .enable = _clk_enable, @@ -675,7 +675,7 @@ static struct clk uart_clk[] = { .enable_shift = MXC_CCM_CGR0_UART1_OFFSET, .disable = _clk_disable,}, { - .name = "uart_clk", + .name = "uart", .id = 1, .parent = &perclk_clk, .enable = _clk_enable, @@ -683,7 +683,7 @@ static struct clk uart_clk[] = { .enable_shift = MXC_CCM_CGR0_UART2_OFFSET, .disable = _clk_disable,}, { - .name = "uart_clk", + .name = "uart", .id = 2, .parent = &perclk_clk, .enable = _clk_enable, @@ -691,7 +691,7 @@ static struct clk uart_clk[] = { .enable_shift = MXC_CCM_CGR1_UART3_OFFSET, .disable = _clk_disable,}, { - .name = "uart_clk", + .name = "uart", .id = 3, .parent = &perclk_clk, .enable = _clk_enable, @@ -699,7 +699,7 @@ static struct clk uart_clk[] = { .enable_shift = MXC_CCM_CGR1_UART4_OFFSET, .disable = _clk_disable,}, { - .name = "uart_clk", + .name = "uart", .id = 4, .parent = &perclk_clk, .enable = _clk_enable, @@ -736,7 +736,7 @@ static struct clk i2c_clk[] = { }; static struct clk owire_clk = { - .name = "owire_clk", + .name = "owire", .parent = &perclk_clk, .enable_reg = MXC_CCM_CGR1, .enable_shift = MXC_CCM_CGR1_OWIRE_OFFSET, diff --git a/arch/arm/plat-mxc/dma-mx1-mx2.c b/arch/arm/plat-mxc/dma-mx1-mx2.c index 2905ec758758..1d64287c3078 100644 --- a/arch/arm/plat-mxc/dma-mx1-mx2.c +++ b/arch/arm/plat-mxc/dma-mx1-mx2.c @@ -802,7 +802,7 @@ static int __init imx_dma_init(void) int ret = 0; int i; - dma_clk = clk_get(NULL, "dma_clk"); + dma_clk = clk_get(NULL, "dma"); clk_enable(dma_clk); /* reset DMA module */ diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 21fd4f1c4806..bad048aca89a 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -880,7 +880,7 @@ static int __init mxcnd_probe(struct platform_device *pdev) this->read_buf = mxc_nand_read_buf; this->verify_buf = mxc_nand_verify_buf; - host->clk = clk_get(&pdev->dev, "nfc_clk"); + host->clk = clk_get(&pdev->dev, "nfc"); if (IS_ERR(host->clk)) goto eclk; diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index a50954612b60..9f460b175c50 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c @@ -1129,7 +1129,7 @@ static int serial_imx_probe(struct platform_device *pdev) sport->timer.function = imx_timeout; sport->timer.data = (unsigned long)sport; - sport->clk = clk_get(&pdev->dev, "uart_clk"); + sport->clk = clk_get(&pdev->dev, "uart"); if (IS_ERR(sport->clk)) { ret = PTR_ERR(sport->clk); goto unmap; diff --git a/drivers/w1/masters/mxc_w1.c b/drivers/w1/masters/mxc_w1.c index b9d74d0b353e..65244c02551b 100644 --- a/drivers/w1/masters/mxc_w1.c +++ b/drivers/w1/masters/mxc_w1.c @@ -116,7 +116,7 @@ static int __init mxc_w1_probe(struct platform_device *pdev) if (!mdev) return -ENOMEM; - mdev->clk = clk_get(&pdev->dev, "owire_clk"); + mdev->clk = clk_get(&pdev->dev, "owire"); if (!mdev->clk) { err = -ENODEV; goto failed_clk; -- cgit v1.2.3