You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branches 'common/clkfwk', 'common/pfc' and 'common/serial-rework' into sh-latest
This commit is contained in:
@@ -46,6 +46,7 @@ static inline char __dcc_getchar(void)
|
||||
|
||||
asm volatile("mrc p14, 0, %0, c0, c5, 0 @ read comms data reg"
|
||||
: "=r" (__c));
|
||||
isb();
|
||||
|
||||
return __c;
|
||||
}
|
||||
@@ -55,6 +56,7 @@ static inline void __dcc_putchar(char c)
|
||||
asm volatile("mcr p14, 0, %0, c0, c5, 0 @ write a char"
|
||||
: /* no output register */
|
||||
: "r" (c));
|
||||
isb();
|
||||
}
|
||||
|
||||
static int hvc_dcc_put_chars(uint32_t vt, const char *buf, int count)
|
||||
|
||||
@@ -1560,7 +1560,7 @@ config SERIAL_IFX6X60
|
||||
Support for the IFX6x60 modem devices on Intel MID platforms.
|
||||
|
||||
config SERIAL_PCH_UART
|
||||
tristate "Intel EG20T PCH / OKI SEMICONDUCTOR IOH(ML7213/ML7223) UART"
|
||||
tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) UART"
|
||||
depends on PCI
|
||||
select SERIAL_CORE
|
||||
help
|
||||
@@ -1568,12 +1568,12 @@ config SERIAL_PCH_UART
|
||||
which is an IOH(Input/Output Hub) for x86 embedded processor.
|
||||
Enabling PCH_DMA, this PCH UART works as DMA mode.
|
||||
|
||||
This driver also can be used for OKI SEMICONDUCTOR IOH(Input/
|
||||
Output Hub), ML7213 and ML7223.
|
||||
ML7213 IOH is for IVI(In-Vehicle Infotainment) use and ML7223 IOH is
|
||||
for MP(Media Phone) use.
|
||||
ML7213/ML7223 is companion chip for Intel Atom E6xx series.
|
||||
ML7213/ML7223 is completely compatible for Intel EG20T PCH.
|
||||
This driver also can be used for LAPIS Semiconductor IOH(Input/
|
||||
Output Hub), ML7213, ML7223 and ML7831.
|
||||
ML7213 IOH is for IVI(In-Vehicle Infotainment) use, ML7223 IOH is
|
||||
for MP(Media Phone) use and ML7831 IOH is for general purpose use.
|
||||
ML7213/ML7223/ML7831 is companion chip for Intel Atom E6xx series.
|
||||
ML7213/ML7223/ML7831 is completely compatible for Intel EG20T PCH.
|
||||
|
||||
config SERIAL_MSM_SMD
|
||||
bool "Enable tty device interface for some SMD ports"
|
||||
|
||||
@@ -228,7 +228,7 @@ void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf)
|
||||
if (rs485conf->flags & SER_RS485_ENABLED) {
|
||||
dev_dbg(port->dev, "Setting UART to RS485\n");
|
||||
atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
|
||||
if (rs485conf->flags & SER_RS485_RTS_AFTER_SEND)
|
||||
if ((rs485conf->delay_rts_after_send) > 0)
|
||||
UART_PUT_TTGR(port, rs485conf->delay_rts_after_send);
|
||||
mode |= ATMEL_US_USMODE_RS485;
|
||||
} else {
|
||||
@@ -304,7 +304,7 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
|
||||
|
||||
if (atmel_port->rs485.flags & SER_RS485_ENABLED) {
|
||||
dev_dbg(port->dev, "Setting UART to RS485\n");
|
||||
if (atmel_port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
|
||||
if ((atmel_port->rs485.delay_rts_after_send) > 0)
|
||||
UART_PUT_TTGR(port,
|
||||
atmel_port->rs485.delay_rts_after_send);
|
||||
mode |= ATMEL_US_USMODE_RS485;
|
||||
@@ -1228,7 +1228,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
|
||||
if (atmel_port->rs485.flags & SER_RS485_ENABLED) {
|
||||
dev_dbg(port->dev, "Setting UART to RS485\n");
|
||||
if (atmel_port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
|
||||
if ((atmel_port->rs485.delay_rts_after_send) > 0)
|
||||
UART_PUT_TTGR(port,
|
||||
atmel_port->rs485.delay_rts_after_send);
|
||||
mode |= ATMEL_US_USMODE_RS485;
|
||||
@@ -1447,16 +1447,6 @@ static void __devinit atmel_of_init_port(struct atmel_uart_port *atmel_port,
|
||||
rs485conf->delay_rts_after_send = rs485_delay[1];
|
||||
rs485conf->flags = 0;
|
||||
|
||||
if (rs485conf->delay_rts_before_send == 0 &&
|
||||
rs485conf->delay_rts_after_send == 0) {
|
||||
rs485conf->flags |= SER_RS485_RTS_ON_SEND;
|
||||
} else {
|
||||
if (rs485conf->delay_rts_before_send)
|
||||
rs485conf->flags |= SER_RS485_RTS_BEFORE_SEND;
|
||||
if (rs485conf->delay_rts_after_send)
|
||||
rs485conf->flags |= SER_RS485_RTS_AFTER_SEND;
|
||||
}
|
||||
|
||||
if (of_get_property(np, "rs485-rx-during-tx", NULL))
|
||||
rs485conf->flags |= SER_RS485_RX_DURING_TX;
|
||||
|
||||
|
||||
@@ -3234,9 +3234,8 @@ rs_write(struct tty_struct *tty,
|
||||
e100_disable_rx(info);
|
||||
e100_enable_rx_irq(info);
|
||||
#endif
|
||||
if ((info->rs485.flags & SER_RS485_RTS_BEFORE_SEND) &&
|
||||
(info->rs485.delay_rts_before_send > 0))
|
||||
msleep(info->rs485.delay_rts_before_send);
|
||||
if (info->rs485.delay_rts_before_send > 0)
|
||||
msleep(info->rs485.delay_rts_before_send);
|
||||
}
|
||||
#endif /* CONFIG_ETRAX_RS485 */
|
||||
|
||||
@@ -3693,10 +3692,6 @@ rs_ioctl(struct tty_struct *tty,
|
||||
|
||||
rs485data.delay_rts_before_send = rs485ctrl.delay_rts_before_send;
|
||||
rs485data.flags = 0;
|
||||
if (rs485data.delay_rts_before_send != 0)
|
||||
rs485data.flags |= SER_RS485_RTS_BEFORE_SEND;
|
||||
else
|
||||
rs485data.flags &= ~(SER_RS485_RTS_BEFORE_SEND);
|
||||
|
||||
if (rs485ctrl.enabled)
|
||||
rs485data.flags |= SER_RS485_ENABLED;
|
||||
@@ -4531,7 +4526,6 @@ static int __init rs_init(void)
|
||||
/* Set sane defaults */
|
||||
info->rs485.flags &= ~(SER_RS485_RTS_ON_SEND);
|
||||
info->rs485.flags |= SER_RS485_RTS_AFTER_SEND;
|
||||
info->rs485.flags &= ~(SER_RS485_RTS_BEFORE_SEND);
|
||||
info->rs485.delay_rts_before_send = 0;
|
||||
info->rs485.flags &= ~(SER_RS485_ENABLED);
|
||||
#endif
|
||||
|
||||
@@ -884,7 +884,6 @@ serial_hsu_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
{
|
||||
struct uart_hsu_port *up =
|
||||
container_of(port, struct uart_hsu_port, port);
|
||||
struct tty_struct *tty = port->state->port.tty;
|
||||
unsigned char cval, fcr = 0;
|
||||
unsigned long flags;
|
||||
unsigned int baud, quot;
|
||||
@@ -907,8 +906,7 @@ serial_hsu_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
}
|
||||
|
||||
/* CMSPAR isn't supported by this driver */
|
||||
if (tty)
|
||||
tty->termios->c_cflag &= ~CMSPAR;
|
||||
termios->c_cflag &= ~CMSPAR;
|
||||
|
||||
if (termios->c_cflag & CSTOPB)
|
||||
cval |= UART_LCR_STOP;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
*Copyright (C) 2010 OKI SEMICONDUCTOR CO., LTD.
|
||||
*Copyright (C) 2011 LAPIS Semiconductor Co., Ltd.
|
||||
*
|
||||
*This program is free software; you can redistribute it and/or modify
|
||||
*it under the terms of the GNU General Public License as published by
|
||||
@@ -46,8 +46,8 @@ enum {
|
||||
|
||||
/* Set the max number of UART port
|
||||
* Intel EG20T PCH: 4 port
|
||||
* OKI SEMICONDUCTOR ML7213 IOH: 3 port
|
||||
* OKI SEMICONDUCTOR ML7223 IOH: 2 port
|
||||
* LAPIS Semiconductor ML7213 IOH: 3 port
|
||||
* LAPIS Semiconductor ML7223 IOH: 2 port
|
||||
*/
|
||||
#define PCH_UART_NR 4
|
||||
|
||||
@@ -258,6 +258,8 @@ enum pch_uart_num_t {
|
||||
pch_ml7213_uart2,
|
||||
pch_ml7223_uart0,
|
||||
pch_ml7223_uart1,
|
||||
pch_ml7831_uart0,
|
||||
pch_ml7831_uart1,
|
||||
};
|
||||
|
||||
static struct pch_uart_driver_data drv_dat[] = {
|
||||
@@ -270,6 +272,8 @@ static struct pch_uart_driver_data drv_dat[] = {
|
||||
[pch_ml7213_uart2] = {PCH_UART_2LINE, 2},
|
||||
[pch_ml7223_uart0] = {PCH_UART_8LINE, 0},
|
||||
[pch_ml7223_uart1] = {PCH_UART_2LINE, 1},
|
||||
[pch_ml7831_uart0] = {PCH_UART_8LINE, 0},
|
||||
[pch_ml7831_uart1] = {PCH_UART_2LINE, 1},
|
||||
};
|
||||
|
||||
static unsigned int default_baud = 9600;
|
||||
@@ -628,6 +632,7 @@ static void pch_request_dma(struct uart_port *port)
|
||||
dev_err(priv->port.dev, "%s:dma_request_channel FAILS(Rx)\n",
|
||||
__func__);
|
||||
dma_release_channel(priv->chan_tx);
|
||||
priv->chan_tx = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1215,8 +1220,7 @@ static void pch_uart_shutdown(struct uart_port *port)
|
||||
dev_err(priv->port.dev,
|
||||
"pch_uart_hal_set_fifo Failed(ret=%d)\n", ret);
|
||||
|
||||
if (priv->use_dma_flag)
|
||||
pch_free_dma(port);
|
||||
pch_free_dma(port);
|
||||
|
||||
free_irq(priv->port.irq, priv);
|
||||
}
|
||||
@@ -1280,6 +1284,7 @@ static void pch_uart_set_termios(struct uart_port *port,
|
||||
if (rtn)
|
||||
goto out;
|
||||
|
||||
pch_uart_set_mctrl(&priv->port, priv->port.mctrl);
|
||||
/* Don't rewrite B0 */
|
||||
if (tty_termios_baud_rate(termios))
|
||||
tty_termios_encode_baud_rate(termios, baud, baud);
|
||||
@@ -1552,6 +1557,10 @@ static DEFINE_PCI_DEVICE_TABLE(pch_uart_pci_id) = {
|
||||
.driver_data = pch_ml7223_uart0},
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x800D),
|
||||
.driver_data = pch_ml7223_uart1},
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8811),
|
||||
.driver_data = pch_ml7831_uart0},
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8812),
|
||||
.driver_data = pch_ml7831_uart1},
|
||||
{0,},
|
||||
};
|
||||
|
||||
|
||||
+165
-18
@@ -50,6 +50,7 @@
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
#ifdef CONFIG_SUPERH
|
||||
#include <asm/sh_bios.h>
|
||||
@@ -73,6 +74,7 @@ struct sci_port {
|
||||
struct clk *fclk;
|
||||
|
||||
char *irqstr[SCIx_NR_IRQS];
|
||||
char *gpiostr[SCIx_NR_FNS];
|
||||
|
||||
struct dma_chan *chan_tx;
|
||||
struct dma_chan *chan_rx;
|
||||
@@ -474,8 +476,15 @@ static void sci_init_pins(struct uart_port *port, unsigned int cflag)
|
||||
if (!reg->size)
|
||||
return;
|
||||
|
||||
if (!(cflag & CRTSCTS))
|
||||
sci_out(port, SCSPTR, 0x0080); /* Set RTS = 1 */
|
||||
if ((s->cfg->capabilities & SCIx_HAVE_RTSCTS) &&
|
||||
((!(cflag & CRTSCTS)))) {
|
||||
unsigned short status;
|
||||
|
||||
status = sci_in(port, SCSPTR);
|
||||
status &= ~SCSPTR_CTSIO;
|
||||
status |= SCSPTR_RTSIO;
|
||||
sci_out(port, SCSPTR, status); /* Set RTS = 1 */
|
||||
}
|
||||
}
|
||||
|
||||
static int sci_txfill(struct uart_port *port)
|
||||
@@ -621,6 +630,7 @@ static void sci_receive_chars(struct uart_port *port)
|
||||
} else {
|
||||
for (i = 0; i < count; i++) {
|
||||
char c = sci_in(port, SCxRDR);
|
||||
|
||||
status = sci_in(port, SCxSR);
|
||||
#if defined(CONFIG_CPU_SH3)
|
||||
/* Skip "chars" during break */
|
||||
@@ -649,9 +659,11 @@ static void sci_receive_chars(struct uart_port *port)
|
||||
/* Store data and status */
|
||||
if (status & SCxSR_FER(port)) {
|
||||
flag = TTY_FRAME;
|
||||
port->icount.frame++;
|
||||
dev_notice(port->dev, "frame error\n");
|
||||
} else if (status & SCxSR_PER(port)) {
|
||||
flag = TTY_PARITY;
|
||||
port->icount.parity++;
|
||||
dev_notice(port->dev, "parity error\n");
|
||||
} else
|
||||
flag = TTY_NORMAL;
|
||||
@@ -723,6 +735,8 @@ static int sci_handle_errors(struct uart_port *port)
|
||||
*/
|
||||
if (s->cfg->overrun_bit != SCIx_NOT_SUPPORTED) {
|
||||
if (status & (1 << s->cfg->overrun_bit)) {
|
||||
port->icount.overrun++;
|
||||
|
||||
/* overrun error */
|
||||
if (tty_insert_flip_char(tty, 0, TTY_OVERRUN))
|
||||
copied++;
|
||||
@@ -737,6 +751,8 @@ static int sci_handle_errors(struct uart_port *port)
|
||||
struct sci_port *sci_port = to_sci_port(port);
|
||||
|
||||
if (!sci_port->break_flag) {
|
||||
port->icount.brk++;
|
||||
|
||||
sci_port->break_flag = 1;
|
||||
sci_schedule_break_timer(sci_port);
|
||||
|
||||
@@ -752,6 +768,8 @@ static int sci_handle_errors(struct uart_port *port)
|
||||
|
||||
} else {
|
||||
/* frame error */
|
||||
port->icount.frame++;
|
||||
|
||||
if (tty_insert_flip_char(tty, 0, TTY_FRAME))
|
||||
copied++;
|
||||
|
||||
@@ -761,6 +779,8 @@ static int sci_handle_errors(struct uart_port *port)
|
||||
|
||||
if (status & SCxSR_PER(port)) {
|
||||
/* parity error */
|
||||
port->icount.parity++;
|
||||
|
||||
if (tty_insert_flip_char(tty, 0, TTY_PARITY))
|
||||
copied++;
|
||||
|
||||
@@ -787,6 +807,8 @@ static int sci_handle_fifo_overrun(struct uart_port *port)
|
||||
if ((sci_in(port, SCLSR) & (1 << s->cfg->overrun_bit))) {
|
||||
sci_out(port, SCLSR, 0);
|
||||
|
||||
port->icount.overrun++;
|
||||
|
||||
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
|
||||
tty_flip_buffer_push(tty);
|
||||
|
||||
@@ -812,6 +834,9 @@ static int sci_handle_breaks(struct uart_port *port)
|
||||
/* Debounce break */
|
||||
s->break_flag = 1;
|
||||
#endif
|
||||
|
||||
port->icount.brk++;
|
||||
|
||||
/* Notify of BREAK */
|
||||
if (tty_insert_flip_char(tty, 0, TTY_BREAK))
|
||||
copied++;
|
||||
@@ -1082,6 +1107,67 @@ static void sci_free_irq(struct sci_port *port)
|
||||
}
|
||||
}
|
||||
|
||||
static const char *sci_gpio_names[SCIx_NR_FNS] = {
|
||||
"sck", "rxd", "txd", "cts", "rts",
|
||||
};
|
||||
|
||||
static const char *sci_gpio_str(unsigned int index)
|
||||
{
|
||||
return sci_gpio_names[index];
|
||||
}
|
||||
|
||||
static void __devinit sci_init_gpios(struct sci_port *port)
|
||||
{
|
||||
struct uart_port *up = &port->port;
|
||||
int i;
|
||||
|
||||
if (!port->cfg)
|
||||
return;
|
||||
|
||||
for (i = 0; i < SCIx_NR_FNS; i++) {
|
||||
const char *desc;
|
||||
int ret;
|
||||
|
||||
if (!port->cfg->gpios[i])
|
||||
continue;
|
||||
|
||||
desc = sci_gpio_str(i);
|
||||
|
||||
port->gpiostr[i] = kasprintf(GFP_KERNEL, "%s:%s",
|
||||
dev_name(up->dev), desc);
|
||||
|
||||
/*
|
||||
* If we've failed the allocation, we can still continue
|
||||
* on with a NULL string.
|
||||
*/
|
||||
if (!port->gpiostr[i])
|
||||
dev_notice(up->dev, "%s string allocation failure\n",
|
||||
desc);
|
||||
|
||||
ret = gpio_request(port->cfg->gpios[i], port->gpiostr[i]);
|
||||
if (unlikely(ret != 0)) {
|
||||
dev_notice(up->dev, "failed %s gpio request\n", desc);
|
||||
|
||||
/*
|
||||
* If we can't get the GPIO for whatever reason,
|
||||
* no point in keeping the verbose string around.
|
||||
*/
|
||||
kfree(port->gpiostr[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void sci_free_gpios(struct sci_port *port)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SCIx_NR_FNS; i++)
|
||||
if (port->cfg->gpios[i]) {
|
||||
gpio_free(port->cfg->gpios[i]);
|
||||
kfree(port->gpiostr[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int sci_tx_empty(struct uart_port *port)
|
||||
{
|
||||
unsigned short status = sci_in(port, SCxSR);
|
||||
@@ -1090,19 +1176,39 @@ static unsigned int sci_tx_empty(struct uart_port *port)
|
||||
return (status & SCxSR_TEND(port)) && !in_tx_fifo ? TIOCSER_TEMT : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Modem control is a bit of a mixed bag for SCI(F) ports. Generally
|
||||
* CTS/RTS is supported in hardware by at least one port and controlled
|
||||
* via SCSPTR (SCxPCR for SCIFA/B parts), or external pins (presently
|
||||
* handled via the ->init_pins() op, which is a bit of a one-way street,
|
||||
* lacking any ability to defer pin control -- this will later be
|
||||
* converted over to the GPIO framework).
|
||||
*
|
||||
* Other modes (such as loopback) are supported generically on certain
|
||||
* port types, but not others. For these it's sufficient to test for the
|
||||
* existence of the support register and simply ignore the port type.
|
||||
*/
|
||||
static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
{
|
||||
/* This routine is used for seting signals of: DTR, DCD, CTS/RTS */
|
||||
/* We use SCIF's hardware for CTS/RTS, so don't need any for that. */
|
||||
/* If you have signals for DTR and DCD, please implement here. */
|
||||
if (mctrl & TIOCM_LOOP) {
|
||||
struct plat_sci_reg *reg;
|
||||
|
||||
/*
|
||||
* Standard loopback mode for SCFCR ports.
|
||||
*/
|
||||
reg = sci_getreg(port, SCFCR);
|
||||
if (reg->size)
|
||||
sci_out(port, SCFCR, sci_in(port, SCFCR) | 1);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int sci_get_mctrl(struct uart_port *port)
|
||||
{
|
||||
/* This routine is used for getting signals of: DTR, DCD, DSR, RI,
|
||||
and CTS/RTS */
|
||||
|
||||
return TIOCM_DTR | TIOCM_RTS | TIOCM_CTS | TIOCM_DSR;
|
||||
/*
|
||||
* CTS/RTS is handled in hardware when supported, while nothing
|
||||
* else is wired up. Keep it simple and simply assert DSR/CAR.
|
||||
*/
|
||||
return TIOCM_DSR | TIOCM_CAR;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SERIAL_SH_SCI_DMA
|
||||
@@ -1449,12 +1555,17 @@ static void sci_stop_rx(struct uart_port *port)
|
||||
|
||||
static void sci_enable_ms(struct uart_port *port)
|
||||
{
|
||||
/* Nothing here yet .. */
|
||||
/*
|
||||
* Not supported by hardware, always a nop.
|
||||
*/
|
||||
}
|
||||
|
||||
static void sci_break_ctl(struct uart_port *port, int break_state)
|
||||
{
|
||||
/* Nothing here yet .. */
|
||||
/*
|
||||
* Not supported by hardware. Most parts couple break and rx
|
||||
* interrupts together, with break detection always enabled.
|
||||
*/
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SERIAL_SH_SCI_DMA
|
||||
@@ -1652,6 +1763,7 @@ static unsigned int sci_scbrr_calc(unsigned int algo_id, unsigned int bps,
|
||||
|
||||
static void sci_reset(struct uart_port *port)
|
||||
{
|
||||
struct plat_sci_reg *reg;
|
||||
unsigned int status;
|
||||
|
||||
do {
|
||||
@@ -1660,7 +1772,8 @@ static void sci_reset(struct uart_port *port)
|
||||
|
||||
sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */
|
||||
|
||||
if (port->type != PORT_SCI)
|
||||
reg = sci_getreg(port, SCFCR);
|
||||
if (reg->size)
|
||||
sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST);
|
||||
}
|
||||
|
||||
@@ -1668,9 +1781,9 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
struct ktermios *old)
|
||||
{
|
||||
struct sci_port *s = to_sci_port(port);
|
||||
struct plat_sci_reg *reg;
|
||||
unsigned int baud, smr_val, max_baud;
|
||||
int t = -1;
|
||||
u16 scfcr = 0;
|
||||
|
||||
/*
|
||||
* earlyprintk comes here early on with port->uartclk set to zero.
|
||||
@@ -1720,7 +1833,27 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
}
|
||||
|
||||
sci_init_pins(port, termios->c_cflag);
|
||||
sci_out(port, SCFCR, scfcr | ((termios->c_cflag & CRTSCTS) ? SCFCR_MCE : 0));
|
||||
|
||||
reg = sci_getreg(port, SCFCR);
|
||||
if (reg->size) {
|
||||
unsigned short ctrl = sci_in(port, SCFCR);
|
||||
|
||||
if (s->cfg->capabilities & SCIx_HAVE_RTSCTS) {
|
||||
if (termios->c_cflag & CRTSCTS)
|
||||
ctrl |= SCFCR_MCE;
|
||||
else
|
||||
ctrl &= ~SCFCR_MCE;
|
||||
}
|
||||
|
||||
/*
|
||||
* As we've done a sci_reset() above, ensure we don't
|
||||
* interfere with the FIFOs while toggling MCE. As the
|
||||
* reset values could still be set, simply mask them out.
|
||||
*/
|
||||
ctrl &= ~(SCFCR_RFRST | SCFCR_TFRST);
|
||||
|
||||
sci_out(port, SCFCR, ctrl);
|
||||
}
|
||||
|
||||
sci_out(port, SCSCR, s->cfg->scscr);
|
||||
|
||||
@@ -1892,6 +2025,8 @@ static int __devinit sci_init_single(struct platform_device *dev,
|
||||
struct uart_port *port = &sci_port->port;
|
||||
int ret;
|
||||
|
||||
sci_port->cfg = p;
|
||||
|
||||
port->ops = &sci_uart_ops;
|
||||
port->iotype = UPIO_MEM;
|
||||
port->line = index;
|
||||
@@ -1937,6 +2072,8 @@ static int __devinit sci_init_single(struct platform_device *dev,
|
||||
|
||||
port->dev = &dev->dev;
|
||||
|
||||
sci_init_gpios(sci_port);
|
||||
|
||||
pm_runtime_irq_safe(&dev->dev);
|
||||
pm_runtime_enable(&dev->dev);
|
||||
}
|
||||
@@ -1971,8 +2108,6 @@ static int __devinit sci_init_single(struct platform_device *dev,
|
||||
p->error_mask |= (1 << p->overrun_bit);
|
||||
}
|
||||
|
||||
sci_port->cfg = p;
|
||||
|
||||
port->mapbase = p->mapbase;
|
||||
port->type = p->type;
|
||||
port->flags = p->flags;
|
||||
@@ -2113,9 +2248,16 @@ static int sci_runtime_suspend(struct device *dev)
|
||||
struct uart_port *port = &sci_port->port;
|
||||
|
||||
if (uart_console(port)) {
|
||||
struct plat_sci_reg *reg;
|
||||
|
||||
sci_port->saved_smr = sci_in(port, SCSMR);
|
||||
sci_port->saved_brr = sci_in(port, SCBRR);
|
||||
sci_port->saved_fcr = sci_in(port, SCFCR);
|
||||
|
||||
reg = sci_getreg(port, SCFCR);
|
||||
if (reg->size)
|
||||
sci_port->saved_fcr = sci_in(port, SCFCR);
|
||||
else
|
||||
sci_port->saved_fcr = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -2129,7 +2271,10 @@ static int sci_runtime_resume(struct device *dev)
|
||||
sci_reset(port);
|
||||
sci_out(port, SCSMR, sci_port->saved_smr);
|
||||
sci_out(port, SCBRR, sci_port->saved_brr);
|
||||
sci_out(port, SCFCR, sci_port->saved_fcr);
|
||||
|
||||
if (sci_port->saved_fcr)
|
||||
sci_out(port, SCFCR, sci_port->saved_fcr);
|
||||
|
||||
sci_out(port, SCSCR, sci_port->cfg->scscr);
|
||||
}
|
||||
return 0;
|
||||
@@ -2169,6 +2314,8 @@ static int sci_remove(struct platform_device *dev)
|
||||
cpufreq_unregister_notifier(&port->freq_transition,
|
||||
CPUFREQ_TRANSITION_NOTIFIER);
|
||||
|
||||
sci_free_gpios(port);
|
||||
|
||||
uart_remove_one_port(&sci_uart_driver, &port->port);
|
||||
|
||||
clk_put(port->iclk);
|
||||
|
||||
+23
-7
@@ -36,6 +36,7 @@
|
||||
|
||||
#include <linux/kmod.h>
|
||||
#include <linux/nsproxy.h>
|
||||
#include <linux/ratelimit.h>
|
||||
|
||||
/*
|
||||
* This guards the refcounted line discipline lists. The lock
|
||||
@@ -547,15 +548,16 @@ static void tty_ldisc_flush_works(struct tty_struct *tty)
|
||||
/**
|
||||
* tty_ldisc_wait_idle - wait for the ldisc to become idle
|
||||
* @tty: tty to wait for
|
||||
* @timeout: for how long to wait at most
|
||||
*
|
||||
* Wait for the line discipline to become idle. The discipline must
|
||||
* have been halted for this to guarantee it remains idle.
|
||||
*/
|
||||
static int tty_ldisc_wait_idle(struct tty_struct *tty)
|
||||
static int tty_ldisc_wait_idle(struct tty_struct *tty, long timeout)
|
||||
{
|
||||
int ret;
|
||||
long ret;
|
||||
ret = wait_event_timeout(tty_ldisc_idle,
|
||||
atomic_read(&tty->ldisc->users) == 1, 5 * HZ);
|
||||
atomic_read(&tty->ldisc->users) == 1, timeout);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return ret > 0 ? 0 : -EBUSY;
|
||||
@@ -665,7 +667,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
|
||||
|
||||
tty_ldisc_flush_works(tty);
|
||||
|
||||
retval = tty_ldisc_wait_idle(tty);
|
||||
retval = tty_ldisc_wait_idle(tty, 5 * HZ);
|
||||
|
||||
tty_lock();
|
||||
mutex_lock(&tty->ldisc_mutex);
|
||||
@@ -762,8 +764,6 @@ static int tty_ldisc_reinit(struct tty_struct *tty, int ldisc)
|
||||
if (IS_ERR(ld))
|
||||
return -1;
|
||||
|
||||
WARN_ON_ONCE(tty_ldisc_wait_idle(tty));
|
||||
|
||||
tty_ldisc_close(tty, tty->ldisc);
|
||||
tty_ldisc_put(tty->ldisc);
|
||||
tty->ldisc = NULL;
|
||||
@@ -838,7 +838,7 @@ void tty_ldisc_hangup(struct tty_struct *tty)
|
||||
tty_unlock();
|
||||
cancel_work_sync(&tty->buf.work);
|
||||
mutex_unlock(&tty->ldisc_mutex);
|
||||
|
||||
retry:
|
||||
tty_lock();
|
||||
mutex_lock(&tty->ldisc_mutex);
|
||||
|
||||
@@ -847,6 +847,22 @@ void tty_ldisc_hangup(struct tty_struct *tty)
|
||||
it means auditing a lot of other paths so this is
|
||||
a FIXME */
|
||||
if (tty->ldisc) { /* Not yet closed */
|
||||
if (atomic_read(&tty->ldisc->users) != 1) {
|
||||
char cur_n[TASK_COMM_LEN], tty_n[64];
|
||||
long timeout = 3 * HZ;
|
||||
tty_unlock();
|
||||
|
||||
while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) {
|
||||
timeout = MAX_SCHEDULE_TIMEOUT;
|
||||
printk_ratelimited(KERN_WARNING
|
||||
"%s: waiting (%s) for %s took too long, but we keep waiting...\n",
|
||||
__func__, get_task_comm(cur_n, current),
|
||||
tty_name(tty, tty_n));
|
||||
}
|
||||
mutex_unlock(&tty->ldisc_mutex);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
if (reset == 0) {
|
||||
|
||||
if (!tty_ldisc_reinit(tty, tty->termios->c_line))
|
||||
|
||||
Reference in New Issue
Block a user