1
0
Fork 0

TTY / Serial driver update for 3.17-rc1

Here's the big tty / serial driver update for 3.17-rc1.
 
 Nothing major, just a number of fixes and new features for different
 serial drivers, and some more tty core fixes and documentation of the
 tty locks.
 
 All of these have been in linux-next for a while.
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2
 
 iEYEABECAAYFAlPf2C4ACgkQMUfUDdst+yllVgCgtZl/Mcr/LlxPgjsg2C1AE7nX
 YJ4An3o4N112bkdGqhZ7RjAE6K/8YILx
 =rPhE
 -----END PGP SIGNATURE-----

Merge tag 'tty-3.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty

Pull tty / serial driver update from Greg KH:
 "Here's the big tty / serial driver update for 3.17-rc1.

  Nothing major, just a number of fixes and new features for different
  serial drivers, and some more tty core fixes and documentation of the
  tty locks.

  All of these have been in linux-next for a while"

* tag 'tty-3.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (82 commits)
  tty/n_gsm.c: fix a memory leak in gsmld_open
  pch_uart: don't hardcode PCI slot to get DMA device
  tty: n_gsm, use setup_timer
  Revert "ARC: [arcfpga] stdout-path now suffices for earlycon/console"
  serial: sc16is7xx: Correct initialization of s->clk
  serial: 8250_dw: Add support for deferred probing
  serial: 8250_dw: Add optional reset control support
  serial: st-asc: Fix overflow in baudrate calculation
  serial: st-asc: Don't call BUG in asc_console_setup()
  tty: serial: msm: Make of_device_id array const
  tty/n_gsm.c: get gsm->num after gsm_activate_mux
  serial/core: Fix too big allocation for attribute member
  drivers/tty/serial: use correct type for dma_map/unmap
  serial: altera_jtaguart: Fix putchar function passed to uart_console_write()
  serial/uart/8250: Add tunable RX interrupt trigger I/F of FIFO buffers
  Serial: allow port drivers to have a default attribute group
  tty: kgdb_nmi: Automatically manage tty enable
  serial: altera_jtaguart: Adpot uart_console_write()
  serial: samsung: improve code clarity by defining a variable
  serial: samsung: correct the case and default order in switch
  ...
wifi-calibration
Linus Torvalds 2014-08-04 18:51:19 -07:00
commit 79eb238c76
93 changed files with 1583 additions and 1048 deletions

View File

@ -138,3 +138,19 @@ Description:
These sysfs values expose the TIOCGSERIAL interface via
sysfs rather than via ioctls.
What: /sys/class/tty/ttyS0/rx_trig_bytes
Date: May 2014
Contact: Yoshihiro YUNOMAE <yoshihiro.yunomae.ez@hitachi.com>
Description:
Shows current RX interrupt trigger bytes or sets the
user specified value to change it for the FIFO buffer.
Users can show or set this value regardless of opening the
serial device file or not.
The RX trigger can be set one of four kinds of values for UART
serials. When users input a meaning less value to this I/F,
the RX trigger is changed to the nearest lower value for the
device specification. For example, when user sets 7bytes on
16550A, which has 1/4/8/14 bytes trigger, the RX trigger is
automatically changed to 4 bytes.

View File

@ -6,7 +6,7 @@ Required properties:
- interrupts : Should contain uart interrupt
Optional properties:
- efm32,location : Decides the location of the USART I/O pins.
- energymicro,location : Decides the location of the USART I/O pins.
Allowed range : [0 .. 5]
Default: 0
@ -16,5 +16,5 @@ uart@0x4000c400 {
compatible = "energymicro,efm32-uart";
reg = <0x4000c400 0x400>;
interrupts = <15>;
efm32,location = <0>;
energymicro,location = <0>;
};

View File

@ -1,7 +1,11 @@
* Freescale low power universal asynchronous receiver/transmitter (lpuart)
Required properties:
- compatible : Should be "fsl,<soc>-lpuart"
- compatible :
- "fsl,vf610-lpuart" for lpuart compatible with the one integrated
on Vybrid vf610 SoC with 8-bit register organization
- "fsl,ls1021a-lpuart" for lpuart compatible with the one integrated
on LS1021A SoC with 32-bit big-endian register organization
- reg : Address and length of the register set for the device
- interrupts : Should contain uart interrupt
- clocks : phandle + clock specifier pairs, one for each entry in clock-names

View File

@ -1,14 +1,58 @@
* Samsung's UART Controller
The Samsung's UART controller is used for interfacing SoC with serial communicaion
devices.
The Samsung's UART controller is used for interfacing SoC with serial
communicaion devices.
Required properties:
- compatible: should be
- "samsung,exynos4210-uart", for UART's compatible with Exynos4210 uart ports.
- compatible: should be one of following:
- "samsung,exynos4210-uart" - Exynos4210 SoC,
- "samsung,s3c2410-uart" - compatible with ports present on S3C2410 SoC,
- "samsung,s3c2412-uart" - compatible with ports present on S3C2412 SoC,
- "samsung,s3c2440-uart" - compatible with ports present on S3C2440 SoC,
- "samsung,s3c6400-uart" - compatible with ports present on S3C6400 SoC,
- "samsung,s5pv210-uart" - compatible with ports present on S5PV210 SoC.
- reg: base physical address of the controller and length of memory mapped
region.
- interrupts: interrupt number to the cpu. The interrupt specifier format depends
on the interrupt controller parent.
- interrupts: a single interrupt signal to SoC interrupt controller,
according to interrupt bindings documentation [1].
- clock-names: input names of clocks used by the controller:
- "uart" - controller bus clock,
- "clk_uart_baudN" - Nth baud base clock input (N = 0, 1, ...),
according to SoC User's Manual (only N = 0 is allowedfor SoCs without
internal baud clock mux).
- clocks: phandles and specifiers for all clocks specified in "clock-names"
property, in the same order, according to clock bindings documentation [2].
[1] Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
[2] Documentation/devicetree/bindings/clock/clock-bindings.txt
Optional properties:
- samsung,uart-fifosize: The fifo size supported by the UART channel
Note: Each Samsung UART should have an alias correctly numbered in the
"aliases" node, according to serialN format, where N is the port number
(non-negative decimal integer) as specified by User's Manual of respective
SoC.
Example:
aliases {
serial0 = &uart0;
serial1 = &uart1;
serial2 = &uart2;
};
Example:
uart1: serial@7f005400 {
compatible = "samsung,s3c6400-uart";
reg = <0x7f005400 0x100>;
interrupt-parent = <&vic1>;
interrupts = <6>;
clock-names = "uart", "clk_uart_baud2",
"clk_uart_baud3";
clocks = <&clocks PCLK_UART1>, <&clocks PCLK_UART1>,
<&clocks SCLK_UART>;
samsung,uart-fifosize = <16>;
};

View File

@ -4,9 +4,18 @@ Required properties:
- compatible : "snps,dw-apb-uart"
- reg : offset and length of the register set for the device.
- interrupts : should contain uart interrupt.
Clock handling:
The clock rate of the input clock needs to be supplied by one of
- clock-frequency : the input clock frequency for the UART.
- clocks : phandle to the input clock
The supplying peripheral clock can also be handled, needing a second property
- clock-names: tuple listing input clock names.
Required elements: "baudclk", "apb_pclk"
Optional properties:
- resets : phandle to the parent reset controller.
- reg-shift : quantity to shift the register offsets by. If this property is
not present then the register offsets are not shifted.
- reg-io-width : the size (in bytes) of the IO accesses that should be
@ -23,3 +32,26 @@ Example:
reg-shift = <2>;
reg-io-width = <4>;
};
Example with one clock:
uart@80230000 {
compatible = "snps,dw-apb-uart";
reg = <0x80230000 0x100>;
clocks = <&baudclk>;
interrupts = <10>;
reg-shift = <2>;
reg-io-width = <4>;
};
Example with two clocks:
uart@80230000 {
compatible = "snps,dw-apb-uart";
reg = <0x80230000 0x100>;
clocks = <&baudclk>, <&apb_pclk>;
clock-names = "baudclk", "apb_pclk";
interrupts = <10>;
reg-shift = <2>;
reg-io-width = <4>;
};

View File

@ -17,7 +17,7 @@
interrupt-parent = <&intc>;
chosen {
bootargs = "console=ttyARC0,115200n8 earlyprintk=ttyARC0";
bootargs = "earlycon=arc_uart,mmio32,0xc0fc1000,115200n8 console=ttyARC0,115200n8";
};
aliases {

View File

@ -41,11 +41,4 @@ config ISS_SMP_EXTN
-XTL (To enable CPU start/stop/set-PC for another CPU)
It doesn't provide coherent Caches and/or Atomic Ops (LLOCK/SCOND)
config ARC_SERIAL_BAUD
int "UART Baud rate"
default "115200"
depends on SERIAL_ARC || SERIAL_ARC_CONSOLE
help
Baud rate for the ARC UART
endif

View File

@ -22,115 +22,22 @@
#include <plat/smp.h>
#include <plat/irq.h>
/*----------------------- Platform Devices -----------------------------*/
#if IS_ENABLED(CONFIG_SERIAL_ARC)
static unsigned long arc_uart_info[] = {
0, /* uart->is_emulated (runtime @running_on_hw) */
0, /* uart->port.uartclk */
0, /* uart->baud */
0
};
#if defined(CONFIG_SERIAL_ARC_CONSOLE)
/*
* static platform data - but only for early serial
* TBD: derive this from a special DT node
*/
static struct resource arc_uart0_res[] = {
{
.start = UART0_BASE,
.end = UART0_BASE + 0xFF,
.flags = IORESOURCE_MEM,
},
{
.start = UART0_IRQ,
.end = UART0_IRQ,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device arc_uart0_dev = {
.name = "arc-uart",
.id = 0,
.num_resources = ARRAY_SIZE(arc_uart0_res),
.resource = arc_uart0_res,
.dev = {
.platform_data = &arc_uart_info,
},
};
static struct platform_device *fpga_early_devs[] __initdata = {
&arc_uart0_dev,
};
#endif /* CONFIG_SERIAL_ARC_CONSOLE */
static void arc_fpga_serial_init(void)
{
/* To let driver workaround ISS bug: baudh Reg can't be set to 0 */
arc_uart_info[0] = !running_on_hw;
arc_uart_info[1] = arc_get_core_freq();
arc_uart_info[2] = CONFIG_ARC_SERIAL_BAUD;
#if defined(CONFIG_SERIAL_ARC_CONSOLE)
early_platform_add_devices(fpga_early_devs,
ARRAY_SIZE(fpga_early_devs));
/*
* ARC console driver registers (build time) as an early platform driver
* of class "earlyprintk". However it needs explicit cmdline toggle
* "earlyprintk=ttyARC0" to be successfuly runtime registered.
* Otherwise the early probe below fails to find the driver
*/
early_platform_driver_probe("earlyprintk", 1, 0);
/*
* This is to make sure that arc uart would be preferred console
* despite one/more of following:
* -command line lacked "console=ttyARC0" or
* -CONFIG_VT_CONSOLE was enabled (for no reason whatsoever)
* Note that this needs to be done after above early console is reg,
* otherwise the early console never gets a chance to run.
*/
add_preferred_console("ttyARC", 0, "115200");
#endif /* CONFIG_SERIAL_ARC_CONSOLE */
}
#else /* !IS_ENABLED(CONFIG_SERIAL_ARC) */
static void arc_fpga_serial_init(void)
{
}
#endif
static void __init plat_fpga_early_init(void)
{
pr_info("[plat-arcfpga]: registering early dev resources\n");
arc_fpga_serial_init();
#ifdef CONFIG_ISS_SMP_EXTN
iss_model_init_early_smp();
#endif
}
static struct of_dev_auxdata plat_auxdata_lookup[] __initdata = {
#if IS_ENABLED(CONFIG_SERIAL_ARC)
OF_DEV_AUXDATA("snps,arc-uart", UART0_BASE, "arc-uart", arc_uart_info),
#endif
{}
};
static void __init plat_fpga_populate_dev(void)
{
pr_info("[plat-arcfpga]: registering device resources\n");
/*
* Traverses flattened DeviceTree - registering platform devices
* complete with their resources
* (if any) complete with their resources
*/
of_platform_populate(NULL, of_default_bus_match_table,
plat_auxdata_lookup, NULL);
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
}
/*----------------------- Machine Descriptions ------------------------------

View File

@ -39,6 +39,8 @@
i2c5 = &i2c_5;
i2c6 = &i2c_6;
i2c7 = &i2c_7;
serial0 = &serial_0;
serial1 = &serial_1;
};
cpus {

View File

@ -44,6 +44,10 @@
fimc1 = &fimc_1;
fimc2 = &fimc_2;
fimc3 = &fimc_3;
serial0 = &serial_0;
serial1 = &serial_1;
serial2 = &serial_2;
serial3 = &serial_3;
};
clock_audss: clock-controller@03810000 {
@ -363,7 +367,7 @@
status = "disabled";
};
serial@13800000 {
serial_0: serial@13800000 {
compatible = "samsung,exynos4210-uart";
reg = <0x13800000 0x100>;
interrupts = <0 52 0>;
@ -372,7 +376,7 @@
status = "disabled";
};
serial@13810000 {
serial_1: serial@13810000 {
compatible = "samsung,exynos4210-uart";
reg = <0x13810000 0x100>;
interrupts = <0 53 0>;
@ -381,7 +385,7 @@
status = "disabled";
};
serial@13820000 {
serial_2: serial@13820000 {
compatible = "samsung,exynos4210-uart";
reg = <0x13820000 0x100>;
interrupts = <0 54 0>;
@ -390,7 +394,7 @@
status = "disabled";
};
serial@13830000 {
serial_3: serial@13830000 {
compatible = "samsung,exynos4210-uart";
reg = <0x13830000 0x100>;
interrupts = <0 55 0>;

View File

@ -18,6 +18,13 @@
/ {
interrupt-parent = <&gic>;
aliases {
serial0 = &serial_0;
serial1 = &serial_1;
serial2 = &serial_2;
serial3 = &serial_3;
};
chipid@10000000 {
compatible = "samsung,exynos4210-chipid";
reg = <0x10000000 0x100>;
@ -50,25 +57,25 @@
interrupts = <1 9 0xf04>;
};
serial@12C00000 {
serial_0: serial@12C00000 {
compatible = "samsung,exynos4210-uart";
reg = <0x12C00000 0x100>;
interrupts = <0 51 0>;
};
serial@12C10000 {
serial_1: serial@12C10000 {
compatible = "samsung,exynos4210-uart";
reg = <0x12C10000 0x100>;
interrupts = <0 52 0>;
};
serial@12C20000 {
serial_2: serial@12C20000 {
compatible = "samsung,exynos4210-uart";
reg = <0x12C20000 0x100>;
interrupts = <0 53 0>;
};
serial@12C30000 {
serial_3: serial@12C30000 {
compatible = "samsung,exynos4210-uart";
reg = <0x12C30000 0x100>;
interrupts = <0 54 0>;

View File

@ -21,6 +21,10 @@
pinctrl0 = &pinctrl_0;
pinctrl1 = &pinctrl_1;
pinctrl2 = &pinctrl_2;
serial0 = &uart0;
serial1 = &uart1;
serial2 = &uart2;
serial3 = &uart3;
};
cpus {

View File

@ -20,6 +20,12 @@
compatible = "samsung,exynos5410", "samsung,exynos5";
interrupt-parent = <&gic>;
aliases {
serial0 = &uart0;
serial1 = &uart1;
serial2 = &uart2;
};
cpus {
#address-cells = <1>;
#size-cells = <0>;

View File

@ -18,6 +18,8 @@
interrupt-parent = <&gic>;
aliases {
serial0 = &serial_0;
serial1 = &serial_1;
spi0 = &spi_0;
tmuctrl0 = &tmuctrl_0;
tmuctrl1 = &tmuctrl_1;
@ -102,7 +104,7 @@
>;
};
serial@B0000 {
serial_0: serial@B0000 {
compatible = "samsung,exynos4210-uart";
reg = <0xB0000 0x1000>;
interrupts = <0 2 0>;
@ -110,7 +112,7 @@
clock-names = "uart", "clk_uart_baud0";
};
serial@C0000 {
serial_1: serial@C0000 {
compatible = "samsung,exynos4210-uart";
reg = <0xC0000 0x1000>;
interrupts = <0 3 0>;

View File

@ -16,6 +16,10 @@
model = "Samsung S3C2416 SoC";
compatible = "samsung,s3c2416";
aliases {
serial3 = &uart3;
};
cpus {
#address-cells = <1>;
#size-cells = <0>;
@ -68,7 +72,7 @@
<&clocks SCLK_UART>;
};
serial@5000C000 {
uart3: serial@5000C000 {
compatible = "samsung,s3c2440-uart";
reg = <0x5000C000 0x4000>;
interrupts = <1 18 24 4>, <1 18 25 4>;

View File

@ -16,6 +16,9 @@
aliases {
pinctrl0 = &pinctrl_0;
serial0 = &uart0;
serial1 = &uart1;
serial2 = &uart2;
};
intc:interrupt-controller@4a000000 {
@ -46,21 +49,21 @@
#pwm-cells = <4>;
};
serial@50000000 {
uart0: serial@50000000 {
compatible = "samsung,s3c2410-uart";
reg = <0x50000000 0x4000>;
interrupts = <1 28 0 4>, <1 28 1 4>;
status = "disabled";
};
serial@50004000 {
uart1: serial@50004000 {
compatible = "samsung,s3c2410-uart";
reg = <0x50004000 0x4000>;
interrupts = <1 23 3 4>, <1 23 4 4>;
status = "disabled";
};
serial@50008000 {
uart2: serial@50008000 {
compatible = "samsung,s3c2410-uart";
reg = <0x50008000 0x4000>;
interrupts = <1 15 6 4>, <1 15 7 4>;

View File

@ -23,6 +23,10 @@
aliases {
i2c0 = &i2c0;
pinctrl0 = &pinctrl0;
serial0 = &uart0;
serial1 = &uart1;
serial2 = &uart2;
serial3 = &uart3;
};
cpus {

View File

@ -2347,8 +2347,6 @@ static void mgslpc_close(struct tty_struct *tty, struct file * filp)
printk("%s(%d):mgslpc_close(%s) entry, count=%d\n",
__FILE__, __LINE__, info->device_name, port->count);
WARN_ON(!port->count);
if (tty_port_close_start(port, tty, filp) == 0)
goto cleanup;
@ -2510,7 +2508,7 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp)
__FILE__, __LINE__, tty->driver->name, port->count);
/* If port is closing, signal caller to try again */
if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING){
if (port->flags & ASYNC_CLOSING){
wait_event_interruptible_tty(tty, port->close_wait,
!(port->flags & ASYNC_CLOSING));
retval = ((port->flags & ASYNC_HUP_NOTIFY) ?

View File

@ -1579,7 +1579,7 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
/*
* If the port is the middle of closing, bail out now
*/
if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) {
if (info->port.flags & ASYNC_CLOSING) {
wait_event_interruptible_tty(tty, info->port.close_wait,
!(info->port.flags & ASYNC_CLOSING));
return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;

View File

@ -93,11 +93,6 @@ static int ipw_open(struct tty_struct *linux_tty, struct file *filp)
return -ENODEV;
mutex_lock(&tty->ipw_tty_mutex);
if (tty->closing) {
mutex_unlock(&tty->ipw_tty_mutex);
return -ENODEV;
}
if (tty->port.count == 0)
tty->tx_bytes_queued = 0;

View File

@ -2088,9 +2088,7 @@ static int gsm_activate_mux(struct gsm_mux *gsm)
struct gsm_dlci *dlci;
int i = 0;
init_timer(&gsm->t2_timer);
gsm->t2_timer.function = gsm_control_retransmit;
gsm->t2_timer.data = (unsigned long)gsm;
setup_timer(&gsm->t2_timer, gsm_control_retransmit, (unsigned long)gsm);
init_waitqueue_head(&gsm->event);
spin_lock_init(&gsm->control_lock);
spin_lock_init(&gsm->tx_lock);
@ -2230,8 +2228,7 @@ static int gsmld_output(struct gsm_mux *gsm, u8 *data, int len)
static int gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)
{
int ret, i;
int base = gsm->num << 6; /* Base for this MUX */
int ret, i, base;
gsm->tty = tty_kref_get(tty);
gsm->output = gsmld_output;
@ -2241,6 +2238,7 @@ static int gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)
else {
/* Don't register device 0 - this is the control channel and not
a usable tty interface */
base = gsm->num << 6; /* Base for this MUX */
for (i = 1; i < NUM_DLCI; i++)
tty_register_device(gsm_tty_driver, base + i, NULL);
}
@ -2368,6 +2366,7 @@ static void gsmld_close(struct tty_struct *tty)
static int gsmld_open(struct tty_struct *tty)
{
struct gsm_mux *gsm;
int ret;
if (tty->ops->write == NULL)
return -EINVAL;
@ -2382,7 +2381,13 @@ static int gsmld_open(struct tty_struct *tty)
/* Attach the initial passive connection */
gsm->encoding = 1;
return gsmld_attach_gsm(tty, gsm);
ret = gsmld_attach_gsm(tty, gsm);
if (ret != 0) {
gsm_cleanup_mux(gsm);
mux_put(gsm);
}
return ret;
}
/**

View File

@ -316,7 +316,7 @@ done:
* pty_common_install - set up the pty pair
* @driver: the pty driver
* @tty: the tty being instantiated
* @bool: legacy, true if this is BSD style
* @legacy: true if this is BSD style
*
* Perform the initial set up for the tty/pty pair. Called from the
* tty layer when the port is first opened.
@ -331,18 +331,17 @@ static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty,
int idx = tty->index;
int retval = -ENOMEM;
o_tty = alloc_tty_struct();
if (!o_tty)
goto err;
ports[0] = kmalloc(sizeof **ports, GFP_KERNEL);
ports[1] = kmalloc(sizeof **ports, GFP_KERNEL);
if (!ports[0] || !ports[1])
goto err_free_tty;
goto err;
if (!try_module_get(driver->other->owner)) {
/* This cannot in fact currently happen */
goto err_free_tty;
goto err;
}
initialize_tty_struct(o_tty, driver->other, idx);
o_tty = alloc_tty_struct(driver->other, idx);
if (!o_tty)
goto err_put_module;
if (legacy) {
/* We always use new tty termios data so we can do this
@ -387,12 +386,12 @@ err_free_termios:
tty_free_termios(tty);
err_deinit_tty:
deinitialize_tty_struct(o_tty);
module_put(o_tty->driver->owner);
err_free_tty:
free_tty_struct(o_tty);
err_put_module:
module_put(driver->other->owner);
err:
kfree(ports[0]);
kfree(ports[1]);
free_tty_struct(o_tty);
err:
return retval;
}

View File

@ -78,10 +78,6 @@ static void serial21285_stop_rx(struct uart_port *port)
}
}
static void serial21285_enable_ms(struct uart_port *port)
{
}
static irqreturn_t serial21285_rx_chars(int irq, void *dev_id)
{
struct uart_port *port = dev_id;
@ -345,7 +341,6 @@ static struct uart_ops serial21285_ops = {
.stop_tx = serial21285_stop_tx,
.start_tx = serial21285_start_tx,
.stop_rx = serial21285_stop_rx,
.enable_ms = serial21285_enable_ms,
.break_ctl = serial21285_break_ctl,
.startup = serial21285_startup,
.shutdown = serial21285_shutdown,

View File

@ -12,6 +12,7 @@
*/
#include <linux/serial_8250.h>
#include <linux/serial_reg.h>
#include <linux/dmaengine.h>
struct uart_8250_dma {
@ -60,6 +61,7 @@ struct serial8250_config {
unsigned short fifo_size;
unsigned short tx_loadsz;
unsigned char fcr;
unsigned char rxtrig_bytes[UART_FCR_R_TRIG_MAX_STATE];
unsigned int flags;
};

View File

@ -31,7 +31,6 @@
#include <linux/tty.h>
#include <linux/ratelimit.h>
#include <linux/tty_flip.h>
#include <linux/serial_reg.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <linux/serial_8250.h>
@ -161,6 +160,7 @@ static const struct serial8250_config uart_config[] = {
.fifo_size = 16,
.tx_loadsz = 16,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.rxtrig_bytes = {1, 4, 8, 14},
.flags = UART_CAP_FIFO,
},
[PORT_CIRRUS] = {
@ -180,6 +180,7 @@ static const struct serial8250_config uart_config[] = {
.tx_loadsz = 16,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
UART_FCR_T_TRIG_00,
.rxtrig_bytes = {8, 16, 24, 28},
.flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
},
[PORT_16750] = {
@ -188,6 +189,7 @@ static const struct serial8250_config uart_config[] = {
.tx_loadsz = 64,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
UART_FCR7_64BYTE,
.rxtrig_bytes = {1, 16, 32, 56},
.flags = UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_AFE,
},
[PORT_STARTECH] = {
@ -209,6 +211,7 @@ static const struct serial8250_config uart_config[] = {
.tx_loadsz = 32,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
UART_FCR_T_TRIG_10,
.rxtrig_bytes = {8, 16, 56, 60},
.flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
},
[PORT_16850] = {
@ -266,6 +269,7 @@ static const struct serial8250_config uart_config[] = {
.tx_loadsz = 8,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
UART_FCR_T_TRIG_01,
.rxtrig_bytes = {1, 4, 8, 14},
.flags = UART_CAP_FIFO | UART_CAP_RTOIE,
},
[PORT_XR17D15X] = {
@ -439,8 +443,7 @@ static int exar_handle_irq(struct uart_port *port);
static void set_io_from_upio(struct uart_port *p)
{
struct uart_8250_port *up =
container_of(p, struct uart_8250_port, port);
struct uart_8250_port *up = up_to_u8250p(p);
up->dl_read = default_serial_dl_read;
up->dl_write = default_serial_dl_write;
@ -531,11 +534,8 @@ static void serial8250_clear_fifos(struct uart_8250_port *p)
void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p)
{
unsigned char fcr;
serial8250_clear_fifos(p);
fcr = uart_config[p->port.type].fcr;
serial_out(p, UART_FCR, fcr);
serial_out(p, UART_FCR, p->fcr);
}
EXPORT_SYMBOL_GPL(serial8250_clear_and_reinit_fifos);
@ -1277,8 +1277,7 @@ static inline void __stop_tx(struct uart_8250_port *p)
static void serial8250_stop_tx(struct uart_port *port)
{
struct uart_8250_port *up =
container_of(port, struct uart_8250_port, port);
struct uart_8250_port *up = up_to_u8250p(port);
__stop_tx(up);
@ -1293,8 +1292,7 @@ static void serial8250_stop_tx(struct uart_port *port)
static void serial8250_start_tx(struct uart_port *port)
{
struct uart_8250_port *up =
container_of(port, struct uart_8250_port, port);
struct uart_8250_port *up = up_to_u8250p(port);
if (up->dma && !serial8250_tx_dma(up)) {
return;
@ -1322,8 +1320,7 @@ static void serial8250_start_tx(struct uart_port *port)
static void serial8250_stop_rx(struct uart_port *port)
{
struct uart_8250_port *up =
container_of(port, struct uart_8250_port, port);
struct uart_8250_port *up = up_to_u8250p(port);
up->ier &= ~UART_IER_RLSI;
up->port.read_status_mask &= ~UART_LSR_DR;
@ -1332,8 +1329,7 @@ static void serial8250_stop_rx(struct uart_port *port)
static void serial8250_enable_ms(struct uart_port *port)
{
struct uart_8250_port *up =
container_of(port, struct uart_8250_port, port);
struct uart_8250_port *up = up_to_u8250p(port);
/* no MSR capabilities */
if (up->bugs & UART_BUG_NOMSR)
@ -1499,8 +1495,7 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
{
unsigned char status;
unsigned long flags;
struct uart_8250_port *up =
container_of(port, struct uart_8250_port, port);
struct uart_8250_port *up = up_to_u8250p(port);
int dma_err = 0;
if (iir & UART_IIR_NO_INT)
@ -1785,8 +1780,7 @@ static void serial8250_backup_timeout(unsigned long data)
static unsigned int serial8250_tx_empty(struct uart_port *port)
{
struct uart_8250_port *up =
container_of(port, struct uart_8250_port, port);
struct uart_8250_port *up = up_to_u8250p(port);
unsigned long flags;
unsigned int lsr;
@ -1800,8 +1794,7 @@ static unsigned int serial8250_tx_empty(struct uart_port *port)
static unsigned int serial8250_get_mctrl(struct uart_port *port)
{
struct uart_8250_port *up =
container_of(port, struct uart_8250_port, port);
struct uart_8250_port *up = up_to_u8250p(port);
unsigned int status;
unsigned int ret;
@ -1821,8 +1814,7 @@ static unsigned int serial8250_get_mctrl(struct uart_port *port)
static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
struct uart_8250_port *up =
container_of(port, struct uart_8250_port, port);
struct uart_8250_port *up = up_to_u8250p(port);
unsigned char mcr = 0;
if (mctrl & TIOCM_RTS)
@ -1843,8 +1835,7 @@ static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
static void serial8250_break_ctl(struct uart_port *port, int break_state)
{
struct uart_8250_port *up =
container_of(port, struct uart_8250_port, port);
struct uart_8250_port *up = up_to_u8250p(port);
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
@ -1911,8 +1902,7 @@ static void serial8250_put_poll_char(struct uart_port *port,
unsigned char c)
{
unsigned int ier;
struct uart_8250_port *up =
container_of(port, struct uart_8250_port, port);
struct uart_8250_port *up = up_to_u8250p(port);
/*
* First save the IER then disable the interrupts
@ -1941,8 +1931,7 @@ static void serial8250_put_poll_char(struct uart_port *port,
static int serial8250_startup(struct uart_port *port)
{
struct uart_8250_port *up =
container_of(port, struct uart_8250_port, port);
struct uart_8250_port *up = up_to_u8250p(port);
unsigned long flags;
unsigned char lsr, iir;
int retval;
@ -2194,8 +2183,7 @@ dont_test_tx_en:
static void serial8250_shutdown(struct uart_port *port)
{
struct uart_8250_port *up =
container_of(port, struct uart_8250_port, port);
struct uart_8250_port *up = up_to_u8250p(port);
unsigned long flags;
/*
@ -2268,12 +2256,10 @@ void
serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old)
{
struct uart_8250_port *up =
container_of(port, struct uart_8250_port, port);
unsigned char cval, fcr = 0;
struct uart_8250_port *up = up_to_u8250p(port);
unsigned char cval;
unsigned long flags;
unsigned int baud, quot;
int fifo_bug = 0;
switch (termios->c_cflag & CSIZE) {
case CS5:
@ -2296,7 +2282,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
if (termios->c_cflag & PARENB) {
cval |= UART_LCR_PARITY;
if (up->bugs & UART_BUG_PARITY)
fifo_bug = 1;
up->fifo_bug = true;
}
if (!(termios->c_cflag & PARODD))
cval |= UART_LCR_EPAR;
@ -2320,10 +2306,10 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
quot++;
if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) {
fcr = uart_config[port->type].fcr;
if ((baud < 2400 && !up->dma) || fifo_bug) {
fcr &= ~UART_FCR_TRIGGER_MASK;
fcr |= UART_FCR_TRIGGER_1;
/* NOTE: If fifo_bug is not set, a user can set RX_trigger. */
if ((baud < 2400 && !up->dma) || up->fifo_bug) {
up->fcr &= ~UART_FCR_TRIGGER_MASK;
up->fcr |= UART_FCR_TRIGGER_1;
}
}
@ -2456,15 +2442,15 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
* is written without DLAB set, this mode will be disabled.
*/
if (port->type == PORT_16750)
serial_port_out(port, UART_FCR, fcr);
serial_port_out(port, UART_FCR, up->fcr);
serial_port_out(port, UART_LCR, cval); /* reset DLAB */
up->lcr = cval; /* Save LCR */
if (port->type != PORT_16750) {
/* emulated UARTs (Lucent Venus 167x) need two steps */
if (fcr & UART_FCR_ENABLE_FIFO)
if (up->fcr & UART_FCR_ENABLE_FIFO)
serial_port_out(port, UART_FCR, UART_FCR_ENABLE_FIFO);
serial_port_out(port, UART_FCR, fcr); /* set fcr */
serial_port_out(port, UART_FCR, up->fcr); /* set fcr */
}
serial8250_set_mctrl(port, port->mctrl);
spin_unlock_irqrestore(&port->lock, flags);
@ -2498,8 +2484,7 @@ serial8250_set_ldisc(struct uart_port *port, int new)
void serial8250_do_pm(struct uart_port *port, unsigned int state,
unsigned int oldstate)
{
struct uart_8250_port *p =
container_of(port, struct uart_8250_port, port);
struct uart_8250_port *p = up_to_u8250p(port);
serial8250_set_sleep(p, state != 0);
}
@ -2630,8 +2615,7 @@ static void serial8250_release_rsa_resource(struct uart_8250_port *up)
static void serial8250_release_port(struct uart_port *port)
{
struct uart_8250_port *up =
container_of(port, struct uart_8250_port, port);
struct uart_8250_port *up = up_to_u8250p(port);
serial8250_release_std_resource(up);
if (port->type == PORT_RSA)
@ -2640,8 +2624,7 @@ static void serial8250_release_port(struct uart_port *port)
static int serial8250_request_port(struct uart_port *port)
{
struct uart_8250_port *up =
container_of(port, struct uart_8250_port, port);
struct uart_8250_port *up = up_to_u8250p(port);
int ret;
if (port->type == PORT_8250_CIR)
@ -2657,10 +2640,149 @@ static int serial8250_request_port(struct uart_port *port)
return ret;
}
static int fcr_get_rxtrig_bytes(struct uart_8250_port *up)
{
const struct serial8250_config *conf_type = &uart_config[up->port.type];
unsigned char bytes;
bytes = conf_type->rxtrig_bytes[UART_FCR_R_TRIG_BITS(up->fcr)];
return bytes ? bytes : -EOPNOTSUPP;
}
static int bytes_to_fcr_rxtrig(struct uart_8250_port *up, unsigned char bytes)
{
const struct serial8250_config *conf_type = &uart_config[up->port.type];
int i;
if (!conf_type->rxtrig_bytes[UART_FCR_R_TRIG_BITS(UART_FCR_R_TRIG_00)])
return -EOPNOTSUPP;
for (i = 1; i < UART_FCR_R_TRIG_MAX_STATE; i++) {
if (bytes < conf_type->rxtrig_bytes[i])
/* Use the nearest lower value */
return (--i) << UART_FCR_R_TRIG_SHIFT;
}
return UART_FCR_R_TRIG_11;
}
static int do_get_rxtrig(struct tty_port *port)
{
struct uart_state *state = container_of(port, struct uart_state, port);
struct uart_port *uport = state->uart_port;
struct uart_8250_port *up =
container_of(uport, struct uart_8250_port, port);
if (!(up->capabilities & UART_CAP_FIFO) || uport->fifosize <= 1)
return -EINVAL;
return fcr_get_rxtrig_bytes(up);
}
static int do_serial8250_get_rxtrig(struct tty_port *port)
{
int rxtrig_bytes;
mutex_lock(&port->mutex);
rxtrig_bytes = do_get_rxtrig(port);
mutex_unlock(&port->mutex);
return rxtrig_bytes;
}
static ssize_t serial8250_get_attr_rx_trig_bytes(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct tty_port *port = dev_get_drvdata(dev);
int rxtrig_bytes;
rxtrig_bytes = do_serial8250_get_rxtrig(port);
if (rxtrig_bytes < 0)
return rxtrig_bytes;
return snprintf(buf, PAGE_SIZE, "%d\n", rxtrig_bytes);
}
static int do_set_rxtrig(struct tty_port *port, unsigned char bytes)
{
struct uart_state *state = container_of(port, struct uart_state, port);
struct uart_port *uport = state->uart_port;
struct uart_8250_port *up =
container_of(uport, struct uart_8250_port, port);
int rxtrig;
if (!(up->capabilities & UART_CAP_FIFO) || uport->fifosize <= 1 ||
up->fifo_bug)
return -EINVAL;
rxtrig = bytes_to_fcr_rxtrig(up, bytes);
if (rxtrig < 0)
return rxtrig;
serial8250_clear_fifos(up);
up->fcr &= ~UART_FCR_TRIGGER_MASK;
up->fcr |= (unsigned char)rxtrig;
serial_out(up, UART_FCR, up->fcr);
return 0;
}
static int do_serial8250_set_rxtrig(struct tty_port *port, unsigned char bytes)
{
int ret;
mutex_lock(&port->mutex);
ret = do_set_rxtrig(port, bytes);
mutex_unlock(&port->mutex);
return ret;
}
static ssize_t serial8250_set_attr_rx_trig_bytes(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct tty_port *port = dev_get_drvdata(dev);
unsigned char bytes;
int ret;
if (!count)
return -EINVAL;
ret = kstrtou8(buf, 10, &bytes);
if (ret < 0)
return ret;
ret = do_serial8250_set_rxtrig(port, bytes);
if (ret < 0)
return ret;
return count;
}
static DEVICE_ATTR(rx_trig_bytes, S_IRUSR | S_IWUSR | S_IRGRP,
serial8250_get_attr_rx_trig_bytes,
serial8250_set_attr_rx_trig_bytes);
static struct attribute *serial8250_dev_attrs[] = {
&dev_attr_rx_trig_bytes.attr,
NULL,
};
static struct attribute_group serial8250_dev_attr_group = {
.attrs = serial8250_dev_attrs,
};
static void register_dev_spec_attr_grp(struct uart_8250_port *up)
{
const struct serial8250_config *conf_type = &uart_config[up->port.type];
if (conf_type->rxtrig_bytes[0])
up->port.attr_group = &serial8250_dev_attr_group;
}
static void serial8250_config_port(struct uart_port *port, int flags)
{
struct uart_8250_port *up =
container_of(port, struct uart_8250_port, port);
struct uart_8250_port *up = up_to_u8250p(port);
int probeflags = PROBE_ANY;
int ret;
@ -2705,6 +2827,9 @@ static void serial8250_config_port(struct uart_port *port, int flags)
if ((port->type == PORT_XR17V35X) ||
(port->type == PORT_XR17D15X))
port->handle_irq = exar_handle_irq;
register_dev_spec_attr_grp(up);
up->fcr = uart_config[up->port.type].fcr;
}
static int
@ -2859,8 +2984,7 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev)
static void serial8250_console_putchar(struct uart_port *port, int ch)
{
struct uart_8250_port *up =
container_of(port, struct uart_8250_port, port);
struct uart_8250_port *up = up_to_u8250p(port);
wait_for_xmitr(up, UART_LSR_THRE);
serial_port_out(port, UART_TX, ch);

View File

@ -26,6 +26,7 @@
#include <linux/slab.h>
#include <linux/acpi.h>
#include <linux/clk.h>
#include <linux/reset.h>
#include <linux/pm_runtime.h>
#include <asm/byteorder.h>
@ -59,73 +60,17 @@ struct dw8250_data {
int last_mcr;
int line;
struct clk *clk;
struct clk *pclk;
struct reset_control *rst;
struct uart_8250_dma dma;
};
struct dw8250_acpi_desc {
void (*set_termios)(struct uart_port *p, struct ktermios *termios,
struct ktermios *old);
};
#define BYT_PRV_CLK 0x800
#define BYT_PRV_CLK_EN (1 << 0)
#define BYT_PRV_CLK_M_VAL_SHIFT 1
#define BYT_PRV_CLK_N_VAL_SHIFT 16
#define BYT_PRV_CLK_UPDATE (1 << 31)
static void byt_set_termios(struct uart_port *p, struct ktermios *termios,
struct ktermios *old)
{
unsigned int baud = tty_termios_baud_rate(termios);
unsigned int m, n;
u32 reg;
/*
* For baud rates 0.5M, 1M, 1.5M, 2M, 2.5M, 3M, 3.5M and 4M the
* dividers must be adjusted.
*
* uartclk = (m / n) * 100 MHz, where m <= n
*/
switch (baud) {
case 500000:
case 1000000:
case 2000000:
case 4000000:
m = 64;
n = 100;
p->uartclk = 64000000;
break;
case 3500000:
m = 56;
n = 100;
p->uartclk = 56000000;
break;
case 1500000:
case 3000000:
m = 48;
n = 100;
p->uartclk = 48000000;
break;
case 2500000:
m = 40;
n = 100;
p->uartclk = 40000000;
break;
default:
m = 2304;
n = 3125;
p->uartclk = 73728000;
}
/* Reset the clock */
reg = (m << BYT_PRV_CLK_M_VAL_SHIFT) | (n << BYT_PRV_CLK_N_VAL_SHIFT);
writel(reg, p->membase + BYT_PRV_CLK);
reg |= BYT_PRV_CLK_EN | BYT_PRV_CLK_UPDATE;
writel(reg, p->membase + BYT_PRV_CLK);
serial8250_do_set_termios(p, termios, old);
}
static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value)
{
struct dw8250_data *d = p->private_data;
@ -141,8 +86,9 @@ static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value)
static void dw8250_force_idle(struct uart_port *p)
{
serial8250_clear_and_reinit_fifos(container_of
(p, struct uart_8250_port, port));
struct uart_8250_port *up = up_to_u8250p(p);
serial8250_clear_and_reinit_fifos(up);
(void)p->serial_in(p, UART_RX);
}
@ -242,6 +188,32 @@ dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
pm_runtime_put_sync_suspend(port->dev);
}
static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
struct ktermios *old)
{
unsigned int baud = tty_termios_baud_rate(termios);
struct dw8250_data *d = p->private_data;
unsigned int rate;
int ret;
if (IS_ERR(d->clk) || !old)
goto out;
/* Not requesting clock rates below 1.8432Mhz */
if (baud < 115200)
baud = 115200;
clk_disable_unprepare(d->clk);
rate = clk_round_rate(d->clk, baud * 16);
ret = clk_set_rate(d->clk, rate);
clk_prepare_enable(d->clk);
if (!ret)
p->uartclk = rate;
out:
serial8250_do_set_termios(p, termios, old);
}
static bool dw8250_dma_filter(struct dma_chan *chan, void *param)
{
struct dw8250_data *data = param;
@ -286,6 +258,7 @@ static int dw8250_probe_of(struct uart_port *p,
struct dw8250_data *data)
{
struct device_node *np = p->dev->of_node;
struct uart_8250_port *up = up_to_u8250p(p);
u32 val;
bool has_ucv = true;
@ -299,7 +272,7 @@ static int dw8250_probe_of(struct uart_port *p,
p->membase += 7;
#endif
p->serial_out = dw8250_serial_out_rb;
p->flags = ASYNC_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE;
p->flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE;
p->type = PORT_OCTEON;
data->usr_reg = 0x27;
has_ucv = false;
@ -318,7 +291,7 @@ static int dw8250_probe_of(struct uart_port *p,
}
}
if (has_ucv)
dw8250_setup_port(container_of(p, struct uart_8250_port, port));
dw8250_setup_port(up);
if (!of_property_read_u32(np, "reg-shift", &val))
p->regshift = val;
@ -340,16 +313,10 @@ static int dw8250_probe_of(struct uart_port *p,
static int dw8250_probe_acpi(struct uart_8250_port *up,
struct dw8250_data *data)
{
const struct acpi_device_id *id;
struct uart_port *p = &up->port;
struct dw8250_acpi_desc *acpi_desc;
dw8250_setup_port(up);
id = acpi_match_device(p->dev->driver->acpi_match_table, p->dev);
if (!id)
return -ENODEV;
p->iotype = UPIO_MEM32;
p->serial_in = dw8250_serial_in32;
p->serial_out = dw8250_serial_out32;
@ -360,12 +327,7 @@ static int dw8250_probe_acpi(struct uart_8250_port *up,
up->dma->rxconf.src_maxburst = p->fifosize / 4;
up->dma->txconf.dst_maxburst = p->fifosize / 4;
acpi_desc = (struct dw8250_acpi_desc *)id->driver_data;
if (!acpi_desc)
return 0;
if (acpi_desc->set_termios)
p->set_termios = acpi_desc->set_termios;
up->port.set_termios = dw8250_set_termios;
return 0;
}
@ -402,12 +364,41 @@ static int dw8250_probe(struct platform_device *pdev)
return -ENOMEM;
data->usr_reg = DW_UART_USR;
data->clk = devm_clk_get(&pdev->dev, NULL);
data->clk = devm_clk_get(&pdev->dev, "baudclk");
if (IS_ERR(data->clk) && PTR_ERR(data->clk) != -EPROBE_DEFER)
data->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(data->clk) && PTR_ERR(data->clk) == -EPROBE_DEFER)
return -EPROBE_DEFER;
if (!IS_ERR(data->clk)) {
clk_prepare_enable(data->clk);
uart.port.uartclk = clk_get_rate(data->clk);
err = clk_prepare_enable(data->clk);
if (err)
dev_warn(&pdev->dev, "could not enable optional baudclk: %d\n",
err);
else
uart.port.uartclk = clk_get_rate(data->clk);
}
data->pclk = devm_clk_get(&pdev->dev, "apb_pclk");
if (IS_ERR(data->clk) && PTR_ERR(data->clk) == -EPROBE_DEFER) {
err = -EPROBE_DEFER;
goto err_clk;
}
if (!IS_ERR(data->pclk)) {
err = clk_prepare_enable(data->pclk);
if (err) {
dev_err(&pdev->dev, "could not enable apb_pclk\n");
goto err_clk;
}
}
data->rst = devm_reset_control_get_optional(&pdev->dev, NULL);
if (IS_ERR(data->rst) && PTR_ERR(data->rst) == -EPROBE_DEFER) {
err = -EPROBE_DEFER;
goto err_pclk;
}
if (!IS_ERR(data->rst))
reset_control_deassert(data->rst);
data->dma.rx_chan_id = -1;
data->dma.tx_chan_id = -1;
data->dma.rx_param = data;
@ -422,18 +413,21 @@ static int dw8250_probe(struct platform_device *pdev)
if (pdev->dev.of_node) {
err = dw8250_probe_of(&uart.port, data);
if (err)
return err;
goto err_reset;
} else if (ACPI_HANDLE(&pdev->dev)) {
err = dw8250_probe_acpi(&uart, data);
if (err)
return err;
goto err_reset;
} else {
return -ENODEV;
err = -ENODEV;
goto err_reset;
}
data->line = serial8250_register_8250_port(&uart);
if (data->line < 0)
return data->line;
if (data->line < 0) {
err = data->line;
goto err_reset;
}
platform_set_drvdata(pdev, data);
@ -441,6 +435,20 @@ static int dw8250_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);
return 0;
err_reset:
if (!IS_ERR(data->rst))
reset_control_assert(data->rst);
err_pclk:
if (!IS_ERR(data->pclk))
clk_disable_unprepare(data->pclk);
err_clk:
if (!IS_ERR(data->clk))
clk_disable_unprepare(data->clk);
return err;
}
static int dw8250_remove(struct platform_device *pdev)
@ -451,6 +459,12 @@ static int dw8250_remove(struct platform_device *pdev)
serial8250_unregister_port(data->line);
if (!IS_ERR(data->rst))
reset_control_assert(data->rst);
if (!IS_ERR(data->pclk))
clk_disable_unprepare(data->pclk);
if (!IS_ERR(data->clk))
clk_disable_unprepare(data->clk);
@ -488,6 +502,9 @@ static int dw8250_runtime_suspend(struct device *dev)
if (!IS_ERR(data->clk))
clk_disable_unprepare(data->clk);
if (!IS_ERR(data->pclk))
clk_disable_unprepare(data->pclk);
return 0;
}
@ -495,6 +512,9 @@ static int dw8250_runtime_resume(struct device *dev)
{
struct dw8250_data *data = dev_get_drvdata(dev);
if (!IS_ERR(data->pclk))
clk_prepare_enable(data->pclk);
if (!IS_ERR(data->clk))
clk_prepare_enable(data->clk);
@ -514,16 +534,12 @@ static const struct of_device_id dw8250_of_match[] = {
};
MODULE_DEVICE_TABLE(of, dw8250_of_match);
static struct dw8250_acpi_desc byt_8250_desc = {
.set_termios = byt_set_termios,
};
static const struct acpi_device_id dw8250_acpi_match[] = {
{ "INT33C4", 0 },
{ "INT33C5", 0 },
{ "INT3434", 0 },
{ "INT3435", 0 },
{ "80860F0A", (kernel_ulong_t)&byt_8250_desc},
{ "80860F0A", 0 },
{ },
};
MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match);

View File

@ -28,8 +28,7 @@ int fsl8250_handle_irq(struct uart_port *port)
unsigned char lsr, orig_lsr;
unsigned long flags;
unsigned int iir;
struct uart_8250_port *up =
container_of(port, struct uart_8250_port, port);
struct uart_8250_port *up = up_to_u8250p(port);
spin_lock_irqsave(&up->port.lock, flags);

View File

@ -1581,8 +1581,7 @@ static int skip_tx_en_setup(struct serial_private *priv,
static void kt_handle_break(struct uart_port *p)
{
struct uart_8250_port *up =
container_of(p, struct uart_8250_port, port);
struct uart_8250_port *up = up_to_u8250p(p);
/*
* On receipt of a BI, serial device in Intel ME (Intel
* management engine) needs to have its fifos cleared for sane
@ -1593,8 +1592,7 @@ static void kt_handle_break(struct uart_port *p)
static unsigned int kt_serial_in(struct uart_port *p, int offset)
{
struct uart_8250_port *up =
container_of(p, struct uart_8250_port, port);
struct uart_8250_port *up = up_to_u8250p(p);
unsigned int val;
/*

View File

@ -238,7 +238,6 @@ config SERIAL_SAMSUNG_UARTS_4
config SERIAL_SAMSUNG_UARTS
int
depends on PLAT_SAMSUNG
default 6 if CPU_S5P6450
default 4 if SERIAL_SAMSUNG_UARTS_4 || CPU_S3C2416
default 3
help
@ -774,7 +773,7 @@ config SERIAL_HS_LPC32XX
config SERIAL_HS_LPC32XX_CONSOLE
bool "Enable LPC32XX high speed UART serial console"
depends on SERIAL_HS_LPC32XX
depends on SERIAL_HS_LPC32XX=y
select SERIAL_CORE_CONSOLE
help
If you would like to be able to use one of the high speed serial
@ -1473,6 +1472,7 @@ config SERIAL_ARC_CONSOLE
bool "Console on ARC UART"
depends on SERIAL_ARC=y
select SERIAL_CORE_CONSOLE
select SERIAL_EARLYCON
help
Enable system Console on ARC UART

View File

@ -109,10 +109,6 @@ static void altera_jtaguart_break_ctl(struct uart_port *port, int break_state)
{
}
static void altera_jtaguart_enable_ms(struct uart_port *port)
{
}
static void altera_jtaguart_set_termios(struct uart_port *port,
struct ktermios *termios,
struct ktermios *old)
@ -291,7 +287,6 @@ static struct uart_ops altera_jtaguart_ops = {
.start_tx = altera_jtaguart_start_tx,
.stop_tx = altera_jtaguart_stop_tx,
.stop_rx = altera_jtaguart_stop_rx,
.enable_ms = altera_jtaguart_enable_ms,
.break_ctl = altera_jtaguart_break_ctl,
.startup = altera_jtaguart_startup,
.shutdown = altera_jtaguart_shutdown,
@ -309,9 +304,8 @@ static struct altera_jtaguart altera_jtaguart_ports[ALTERA_JTAGUART_MAXPORTS];
#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE)
#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS)
static void altera_jtaguart_console_putc(struct console *co, const char c)
static void altera_jtaguart_console_putc(struct uart_port *port, int c)
{
struct uart_port *port = &(altera_jtaguart_ports + co->index)->port;
unsigned long status;
unsigned long flags;
@ -330,9 +324,8 @@ static void altera_jtaguart_console_putc(struct console *co, const char c)
spin_unlock_irqrestore(&port->lock, flags);
}
#else
static void altera_jtaguart_console_putc(struct console *co, const char c)
static void altera_jtaguart_console_putc(struct uart_port *port, int c)
{
struct uart_port *port = &(altera_jtaguart_ports + co->index)->port;
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
@ -350,11 +343,9 @@ static void altera_jtaguart_console_putc(struct console *co, const char c)
static void altera_jtaguart_console_write(struct console *co, const char *s,
unsigned int count)
{
for (; count; count--, s++) {
altera_jtaguart_console_putc(co, *s);
if (*s == '\n')
altera_jtaguart_console_putc(co, '\r');
}
struct uart_port *port = &(altera_jtaguart_ports + co->index)->port;
uart_console_write(port, s, count, altera_jtaguart_console_putc);
}
static int __init altera_jtaguart_console_setup(struct console *co,

View File

@ -163,10 +163,6 @@ static void altera_uart_break_ctl(struct uart_port *port, int break_state)
spin_unlock_irqrestore(&port->lock, flags);
}
static void altera_uart_enable_ms(struct uart_port *port)
{
}
static void altera_uart_set_termios(struct uart_port *port,
struct ktermios *termios,
struct ktermios *old)
@ -415,7 +411,6 @@ static struct uart_ops altera_uart_ops = {
.start_tx = altera_uart_start_tx,
.stop_tx = altera_uart_stop_tx,
.stop_rx = altera_uart_stop_rx,
.enable_ms = altera_uart_enable_ms,
.break_ctl = altera_uart_break_ctl,
.startup = altera_uart_startup,
.shutdown = altera_uart_shutdown,
@ -435,7 +430,7 @@ static struct altera_uart altera_uart_ports[CONFIG_SERIAL_ALTERA_UART_MAXPORTS];
#if defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE)
static void altera_uart_console_putc(struct uart_port *port, const char c)
static void altera_uart_console_putc(struct uart_port *port, int c)
{
while (!(altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
ALTERA_UART_STATUS_TRDY_MSK))
@ -449,11 +444,7 @@ static void altera_uart_console_write(struct console *co, const char *s,
{
struct uart_port *port = &(altera_uart_ports + co->index)->port;
for (; count; count--, s++) {
altera_uart_console_putc(port, *s);
if (*s == '\n')
altera_uart_console_putc(port, '\r');
}
uart_console_write(port, s, count, altera_uart_console_putc);
}
static int __init altera_uart_console_setup(struct console *co, char *options)

View File

@ -46,8 +46,7 @@
#include <linux/amba/serial.h>
#include <linux/clk.h>
#include <linux/slab.h>
#include <asm/io.h>
#include <linux/io.h>
#define UART_NR 8
@ -688,28 +687,22 @@ static int pl010_probe(struct amba_device *dev, const struct amba_id *id)
if (amba_ports[i] == NULL)
break;
if (i == ARRAY_SIZE(amba_ports)) {
ret = -EBUSY;
goto out;
}
if (i == ARRAY_SIZE(amba_ports))
return -EBUSY;
uap = kzalloc(sizeof(struct uart_amba_port), GFP_KERNEL);
if (!uap) {
ret = -ENOMEM;
goto out;
}
uap = devm_kzalloc(&dev->dev, sizeof(struct uart_amba_port),
GFP_KERNEL);
if (!uap)
return -ENOMEM;
base = ioremap(dev->res.start, resource_size(&dev->res));
if (!base) {
ret = -ENOMEM;
goto free;
}
base = devm_ioremap(&dev->dev, dev->res.start,
resource_size(&dev->res));
if (!base)
return -ENOMEM;
uap->clk = clk_get(&dev->dev, NULL);
if (IS_ERR(uap->clk)) {
ret = PTR_ERR(uap->clk);
goto unmap;
}
uap->clk = devm_clk_get(&dev->dev, NULL);
if (IS_ERR(uap->clk))
return PTR_ERR(uap->clk);
uap->port.dev = &dev->dev;
uap->port.mapbase = dev->res.start;
@ -727,15 +720,9 @@ static int pl010_probe(struct amba_device *dev, const struct amba_id *id)
amba_set_drvdata(dev, uap);
ret = uart_add_one_port(&amba_reg, &uap->port);
if (ret) {
if (ret)
amba_ports[i] = NULL;
clk_put(uap->clk);
unmap:
iounmap(base);
free:
kfree(uap);
}
out:
return ret;
}
@ -750,9 +737,6 @@ static int pl010_remove(struct amba_device *dev)
if (amba_ports[i] == uap)
amba_ports[i] = NULL;
iounmap(uap->port.membase);
clk_put(uap->clk);
kfree(uap);
return 0;
}

View File

@ -1484,7 +1484,7 @@ static int pl011_hwinit(struct uart_port *port)
*/
retval = clk_prepare_enable(uap->clk);
if (retval)
goto out;
return retval;
uap->port.uartclk = clk_get_rate(uap->clk);
@ -1507,8 +1507,6 @@ static int pl011_hwinit(struct uart_port *port)
plat->init();
}
return 0;
out:
return retval;
}
static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h)
@ -2131,32 +2129,24 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
if (amba_ports[i] == NULL)
break;
if (i == ARRAY_SIZE(amba_ports)) {
ret = -EBUSY;
goto out;
}
if (i == ARRAY_SIZE(amba_ports))
return -EBUSY;
uap = devm_kzalloc(&dev->dev, sizeof(struct uart_amba_port),
GFP_KERNEL);
if (uap == NULL) {
ret = -ENOMEM;
goto out;
}
if (uap == NULL)
return -ENOMEM;
i = pl011_probe_dt_alias(i, &dev->dev);
base = devm_ioremap(&dev->dev, dev->res.start,
resource_size(&dev->res));
if (!base) {
ret = -ENOMEM;
goto out;
}
if (!base)
return -ENOMEM;
uap->clk = devm_clk_get(&dev->dev, NULL);
if (IS_ERR(uap->clk)) {
ret = PTR_ERR(uap->clk);
goto out;
}
if (IS_ERR(uap->clk))
return PTR_ERR(uap->clk);
uap->vendor = vendor;
uap->lcrh_rx = vendor->lcrh_rx;
@ -2198,7 +2188,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
uart_unregister_driver(&amba_reg);
pl011_dma_remove(uap);
}
out:
return ret;
}

View File

@ -71,11 +71,6 @@ static void apbuart_stop_rx(struct uart_port *port)
UART_PUT_CTRL(port, cr);
}
static void apbuart_enable_ms(struct uart_port *port)
{
/* No modem status change interrupts for APBUART */
}
static void apbuart_rx_chars(struct uart_port *port)
{
unsigned int status, ch, rsr, flag;
@ -337,7 +332,6 @@ static struct uart_ops grlib_apbuart_ops = {
.stop_tx = apbuart_stop_tx,
.start_tx = apbuart_start_tx,
.stop_rx = apbuart_stop_rx,
.enable_ms = apbuart_enable_ms,
.break_ctl = apbuart_break_ctl,
.startup = apbuart_startup,
.shutdown = apbuart_shutdown,

View File

@ -176,10 +176,6 @@ static void ar933x_uart_break_ctl(struct uart_port *port, int break_state)
spin_unlock_irqrestore(&up->port.lock, flags);
}
static void ar933x_uart_enable_ms(struct uart_port *port)
{
}
/*
* baudrate = (clk / (scale + 1)) * (step * (1 / 2^17))
*/
@ -495,7 +491,6 @@ static struct uart_ops ar933x_uart_ops = {
.stop_tx = ar933x_uart_stop_tx,
.start_tx = ar933x_uart_start_tx,
.stop_rx = ar933x_uart_stop_rx,
.enable_ms = ar933x_uart_enable_ms,
.break_ctl = ar933x_uart_break_ctl,
.startup = ar933x_uart_startup,
.shutdown = ar933x_uart_shutdown,

View File

@ -37,8 +37,8 @@
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
/*************************************
* ARC UART Hardware Specs
@ -72,7 +72,7 @@
#define RXOERR 0x02 /* OverFlow Err: Char recv but RXFULL still set */
/* Uart bit fiddling helpers: lowest level */
#define RBASE(uart, reg) (uart->port.membase + reg)
#define RBASE(port, reg) (port->membase + reg)
#define UART_REG_SET(u, r, v) writeb((v), RBASE(u, r))
#define UART_REG_GET(u, r) readb(RBASE(u, r))
@ -102,7 +102,6 @@
struct arc_uart_port {
struct uart_port port;
unsigned long baud;
int is_emulated; /* H/w vs. Instruction Set Simulator */
};
#define to_arc_port(uport) container_of(uport, struct arc_uart_port, port)
@ -129,19 +128,15 @@ static struct uart_driver arc_uart_driver = {
static void arc_serial_stop_rx(struct uart_port *port)
{
struct arc_uart_port *uart = to_arc_port(port);
UART_RX_IRQ_DISABLE(uart);
UART_RX_IRQ_DISABLE(port);
}
static void arc_serial_stop_tx(struct uart_port *port)
{
struct arc_uart_port *uart = to_arc_port(port);
while (!(UART_GET_STATUS(uart) & TXEMPTY))
while (!(UART_GET_STATUS(port) & TXEMPTY))
cpu_relax();
UART_TX_IRQ_DISABLE(uart);
UART_TX_IRQ_DISABLE(port);
}
/*
@ -149,10 +144,9 @@ static void arc_serial_stop_tx(struct uart_port *port)
*/
static unsigned int arc_serial_tx_empty(struct uart_port *port)
{
struct arc_uart_port *uart = to_arc_port(port);
unsigned int stat;
stat = UART_GET_STATUS(uart);
stat = UART_GET_STATUS(port);
if (stat & TXEMPTY)
return TIOCSER_TEMT;
@ -166,24 +160,24 @@ static unsigned int arc_serial_tx_empty(struct uart_port *port)
* = by uart_start( ) before calling us
* = tx_ist checks that too before calling
*/
static void arc_serial_tx_chars(struct arc_uart_port *uart)
static void arc_serial_tx_chars(struct uart_port *port)
{
struct circ_buf *xmit = &uart->port.state->xmit;
struct circ_buf *xmit = &port->state->xmit;
int sent = 0;
unsigned char ch;
if (unlikely(uart->port.x_char)) {
UART_SET_DATA(uart, uart->port.x_char);
uart->port.icount.tx++;
uart->port.x_char = 0;
if (unlikely(port->x_char)) {
UART_SET_DATA(port, port->x_char);
port->icount.tx++;
port->x_char = 0;
sent = 1;
} else if (!uart_circ_empty(xmit)) {
ch = xmit->buf[xmit->tail];
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
uart->port.icount.tx++;
while (!(UART_GET_STATUS(uart) & TXEMPTY))
port->icount.tx++;
while (!(UART_GET_STATUS(port) & TXEMPTY))
cpu_relax();
UART_SET_DATA(uart, ch);
UART_SET_DATA(port, ch);
sent = 1;
}
@ -192,10 +186,10 @@ static void arc_serial_tx_chars(struct arc_uart_port *uart)
* By Hard ISR to schedule processing in software interrupt part
*/
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(&uart->port);
uart_write_wakeup(port);
if (sent)
UART_TX_IRQ_ENABLE(uart);
UART_TX_IRQ_ENABLE(port);
}
/*
@ -204,12 +198,10 @@ static void arc_serial_tx_chars(struct arc_uart_port *uart)
*/
static void arc_serial_start_tx(struct uart_port *port)
{
struct arc_uart_port *uart = to_arc_port(port);
arc_serial_tx_chars(uart);
arc_serial_tx_chars(port);
}
static void arc_serial_rx_chars(struct arc_uart_port *uart, unsigned int status)
static void arc_serial_rx_chars(struct uart_port *port, unsigned int status)
{
unsigned int ch, flg = 0;
@ -229,15 +221,15 @@ static void arc_serial_rx_chars(struct arc_uart_port *uart, unsigned int status)
*/
if (unlikely(status & (RXOERR | RXFERR))) {
if (status & RXOERR) {
uart->port.icount.overrun++;
port->icount.overrun++;
flg = TTY_OVERRUN;
UART_CLR_STATUS(uart, RXOERR);
UART_CLR_STATUS(port, RXOERR);
}
if (status & RXFERR) {
uart->port.icount.frame++;
port->icount.frame++;
flg = TTY_FRAME;
UART_CLR_STATUS(uart, RXFERR);
UART_CLR_STATUS(port, RXFERR);
}
} else
flg = TTY_NORMAL;
@ -245,16 +237,16 @@ static void arc_serial_rx_chars(struct arc_uart_port *uart, unsigned int status)
if (status & RXEMPTY)
continue;
ch = UART_GET_DATA(uart);
uart->port.icount.rx++;
ch = UART_GET_DATA(port);
port->icount.rx++;
if (!(uart_handle_sysrq_char(&uart->port, ch)))
uart_insert_char(&uart->port, status, RXOERR, ch, flg);
if (!(uart_handle_sysrq_char(port, ch)))
uart_insert_char(port, status, RXOERR, ch, flg);
spin_unlock(&uart->port.lock);
tty_flip_buffer_push(&uart->port.state->port);
spin_lock(&uart->port.lock);
} while (!((status = UART_GET_STATUS(uart)) & RXEMPTY));
spin_unlock(&port->lock);
tty_flip_buffer_push(&port->state->port);
spin_lock(&port->lock);
} while (!((status = UART_GET_STATUS(port)) & RXEMPTY));
}
/*
@ -287,10 +279,10 @@ static void arc_serial_rx_chars(struct arc_uart_port *uart, unsigned int status)
static irqreturn_t arc_serial_isr(int irq, void *dev_id)
{
struct arc_uart_port *uart = dev_id;
struct uart_port *port = dev_id;
unsigned int status;
status = UART_GET_STATUS(uart);
status = UART_GET_STATUS(port);
/*
* Single IRQ for both Rx (data available) Tx (room available) Interrupt
@ -300,9 +292,9 @@ static irqreturn_t arc_serial_isr(int irq, void *dev_id)
if (status & RXIENB) {
/* already in ISR, no need of xx_irqsave */
spin_lock(&uart->port.lock);
arc_serial_rx_chars(uart, status);
spin_unlock(&uart->port.lock);
spin_lock(&port->lock);
arc_serial_rx_chars(port, status);
spin_unlock(&port->lock);
}
if ((status & TXIENB) && (status & TXEMPTY)) {
@ -310,14 +302,14 @@ static irqreturn_t arc_serial_isr(int irq, void *dev_id)
/* Unconditionally disable further Tx-Interrupts.
* will be enabled by tx_chars() if needed.
*/
UART_TX_IRQ_DISABLE(uart);
UART_TX_IRQ_DISABLE(port);
spin_lock(&uart->port.lock);
spin_lock(&port->lock);
if (!uart_tx_stopped(&uart->port))
arc_serial_tx_chars(uart);
if (!uart_tx_stopped(port))
arc_serial_tx_chars(port);
spin_unlock(&uart->port.lock);
spin_unlock(&port->lock);
}
return IRQ_HANDLED;
@ -340,13 +332,6 @@ static void arc_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
/* MCR not present */
}
/* Enable Modem Status Interrupts */
static void arc_serial_enable_ms(struct uart_port *port)
{
/* MSR not present */
}
static void arc_serial_break_ctl(struct uart_port *port, int break_state)
{
/* ARC UART doesn't support sending Break signal */
@ -354,18 +339,15 @@ static void arc_serial_break_ctl(struct uart_port *port, int break_state)
static int arc_serial_startup(struct uart_port *port)
{
struct arc_uart_port *uart = to_arc_port(port);
/* Before we hook up the ISR, Disable all UART Interrupts */
UART_ALL_IRQ_DISABLE(uart);
UART_ALL_IRQ_DISABLE(port);
if (request_irq(uart->port.irq, arc_serial_isr, 0, "arc uart rx-tx",
uart)) {
dev_warn(uart->port.dev, "Unable to attach ARC UART intr\n");
if (request_irq(port->irq, arc_serial_isr, 0, "arc uart rx-tx", port)) {
dev_warn(port->dev, "Unable to attach ARC UART intr\n");
return -EBUSY;
}
UART_RX_IRQ_ENABLE(uart); /* Only Rx IRQ enabled to begin with */
UART_RX_IRQ_ENABLE(port); /* Only Rx IRQ enabled to begin with */
return 0;
}
@ -373,8 +355,7 @@ static int arc_serial_startup(struct uart_port *port)
/* This is not really needed */
static void arc_serial_shutdown(struct uart_port *port)
{
struct arc_uart_port *uart = to_arc_port(port);
free_irq(uart->port.irq, uart);
free_irq(port->irq, port);
}
static void
@ -398,25 +379,14 @@ arc_serial_set_termios(struct uart_port *port, struct ktermios *new,
uartl = hw_val & 0xFF;
uarth = (hw_val >> 8) & 0xFF;
/*
* UART ISS(Instruction Set simulator) emulation has a subtle bug:
* A existing value of Baudh = 0 is used as a indication to startup
* it's internal state machine.
* Thus if baudh is set to 0, 2 times, it chokes.
* This happens with BAUD=115200 and the formaula above
* Until that is fixed, when running on ISS, we will set baudh to !0
*/
if (uart->is_emulated)
uarth = 1;
spin_lock_irqsave(&port->lock, flags);
UART_ALL_IRQ_DISABLE(uart);
UART_ALL_IRQ_DISABLE(port);
UART_SET_BAUDL(uart, uartl);
UART_SET_BAUDH(uart, uarth);
UART_SET_BAUDL(port, uartl);
UART_SET_BAUDH(port, uarth);
UART_RX_IRQ_ENABLE(uart);
UART_RX_IRQ_ENABLE(port);
/*
* UART doesn't support Parity/Hardware Flow Control;
@ -439,9 +409,7 @@ arc_serial_set_termios(struct uart_port *port, struct ktermios *new,
static const char *arc_serial_type(struct uart_port *port)
{
struct arc_uart_port *uart = to_arc_port(port);
return uart->port.type == PORT_ARC ? DRIVER_NAME : NULL;
return port->type == PORT_ARC ? DRIVER_NAME : NULL;
}
static void arc_serial_release_port(struct uart_port *port)
@ -470,35 +438,28 @@ arc_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
*/
static void arc_serial_config_port(struct uart_port *port, int flags)
{
struct arc_uart_port *uart = to_arc_port(port);
if (flags & UART_CONFIG_TYPE)
uart->port.type = PORT_ARC;
port->type = PORT_ARC;
}
#if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_ARC_CONSOLE)
#ifdef CONFIG_CONSOLE_POLL
static void arc_serial_poll_putchar(struct uart_port *port, unsigned char chr)
{
struct arc_uart_port *uart = to_arc_port(port);
while (!(UART_GET_STATUS(uart) & TXEMPTY))
while (!(UART_GET_STATUS(port) & TXEMPTY))
cpu_relax();
UART_SET_DATA(uart, chr);
UART_SET_DATA(port, chr);
}
#endif
#ifdef CONFIG_CONSOLE_POLL
static int arc_serial_poll_getchar(struct uart_port *port)
{
struct arc_uart_port *uart = to_arc_port(port);
unsigned char chr;
while (!(UART_GET_STATUS(uart) & RXEMPTY))
while (!(UART_GET_STATUS(port) & RXEMPTY))
cpu_relax();
chr = UART_GET_DATA(uart);
chr = UART_GET_DATA(port);
return chr;
}
#endif
@ -510,7 +471,6 @@ static struct uart_ops arc_serial_pops = {
.stop_tx = arc_serial_stop_tx,
.start_tx = arc_serial_start_tx,
.stop_rx = arc_serial_stop_rx,
.enable_ms = arc_serial_enable_ms,
.break_ctl = arc_serial_break_ctl,
.startup = arc_serial_startup,
.shutdown = arc_serial_shutdown,
@ -526,71 +486,6 @@ static struct uart_ops arc_serial_pops = {
#endif
};
static int
arc_uart_init_one(struct platform_device *pdev, int dev_id)
{
struct resource *res, *res2;
unsigned long *plat_data;
struct arc_uart_port *uart = &arc_uart_ports[dev_id];
plat_data = dev_get_platdata(&pdev->dev);
if (!plat_data)
return -ENODEV;
uart->is_emulated = !!plat_data[0]; /* workaround ISS bug */
if (is_early_platform_device(pdev)) {
uart->port.uartclk = plat_data[1];
uart->baud = plat_data[2];
} else {
struct device_node *np = pdev->dev.of_node;
u32 val;
if (of_property_read_u32(np, "clock-frequency", &val)) {
dev_err(&pdev->dev, "clock-frequency property NOTset\n");
return -EINVAL;
}
uart->port.uartclk = val;
if (of_property_read_u32(np, "current-speed", &val)) {
dev_err(&pdev->dev, "current-speed property NOT set\n");
return -EINVAL;
}
uart->baud = val;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENODEV;
res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!res2)
return -ENODEV;
uart->port.mapbase = res->start;
uart->port.membase = ioremap_nocache(res->start, resource_size(res));
if (!uart->port.membase)
/* No point of dev_err since UART itself is hosed here */
return -ENXIO;
uart->port.irq = res2->start;
uart->port.dev = &pdev->dev;
uart->port.iotype = UPIO_MEM;
uart->port.flags = UPF_BOOT_AUTOCONF;
uart->port.line = dev_id;
uart->port.ops = &arc_serial_pops;
uart->port.fifosize = ARC_UART_TX_FIFO_SIZE;
/*
* uart_insert_char( ) uses it in decideding whether to ignore a
* char or not. Explicitly setting it here, removes the subtelty
*/
uart->port.ignore_status_mask = 0;
return 0;
}
#ifdef CONFIG_SERIAL_ARC_CONSOLE
static int arc_serial_console_setup(struct console *co, char *options)
@ -624,7 +519,10 @@ static int arc_serial_console_setup(struct console *co, char *options)
static void arc_serial_console_putchar(struct uart_port *port, int ch)
{
arc_serial_poll_putchar(port, (unsigned char)ch);
while (!(UART_GET_STATUS(port) & TXEMPTY))
cpu_relax();
UART_SET_DATA(port, (unsigned char)ch);
}
/*
@ -651,48 +549,45 @@ static struct console arc_console = {
.data = &arc_uart_driver
};
static __init void early_serial_write(struct console *con, const char *s,
unsigned int n)
static __init void arc_early_serial_write(struct console *con, const char *s,
unsigned int n)
{
struct uart_port *port = &arc_uart_ports[con->index].port;
unsigned int i;
struct earlycon_device *dev = con->data;
for (i = 0; i < n; i++, s++) {
if (*s == '\n')
arc_serial_poll_putchar(port, '\r');
arc_serial_poll_putchar(port, *s);
}
uart_console_write(&dev->port, s, n, arc_serial_console_putchar);
}
static struct console arc_early_serial_console __initdata = {
.name = "early_ARCuart",
.write = early_serial_write,
.flags = CON_PRINTBUFFER | CON_BOOT,
.index = -1
};
static int __init arc_serial_probe_earlyprintk(struct platform_device *pdev)
static int __init arc_early_console_setup(struct earlycon_device *dev,
const char *opt)
{
int dev_id = pdev->id < 0 ? 0 : pdev->id;
int rc;
struct uart_port *port = &dev->port;
unsigned int l, h, hw_val;
arc_early_serial_console.index = dev_id;
if (!dev->port.membase)
return -ENODEV;
rc = arc_uart_init_one(pdev, dev_id);
if (rc)
panic("early console init failed\n");
hw_val = port->uartclk / (dev->baud * 4) - 1;
l = hw_val & 0xFF;
h = (hw_val >> 8) & 0xFF;
arc_serial_console_setup(&arc_early_serial_console, NULL);
UART_SET_BAUDL(port, l);
UART_SET_BAUDH(port, h);
register_console(&arc_early_serial_console);
dev->con->write = arc_early_serial_write;
return 0;
}
EARLYCON_DECLARE(arc_uart, arc_early_console_setup);
OF_EARLYCON_DECLARE(arc_uart, "snps,arc-uart", arc_early_console_setup);
#endif /* CONFIG_SERIAL_ARC_CONSOLE */
static int arc_serial_probe(struct platform_device *pdev)
{
int rc, dev_id;
struct device_node *np = pdev->dev.of_node;
struct arc_uart_port *uart;
struct uart_port *port;
int dev_id;
u32 val;
/* no device tree device */
if (!np)
@ -702,12 +597,43 @@ static int arc_serial_probe(struct platform_device *pdev)
if (dev_id < 0)
dev_id = 0;
rc = arc_uart_init_one(pdev, dev_id);
if (rc)
return rc;
uart = &arc_uart_ports[dev_id];
port = &uart->port;
rc = uart_add_one_port(&arc_uart_driver, &arc_uart_ports[dev_id].port);
return rc;
if (of_property_read_u32(np, "clock-frequency", &val)) {
dev_err(&pdev->dev, "clock-frequency property NOTset\n");
return -EINVAL;
}
port->uartclk = val;
if (of_property_read_u32(np, "current-speed", &val)) {
dev_err(&pdev->dev, "current-speed property NOT set\n");
return -EINVAL;
}
uart->baud = val;
port->membase = of_iomap(np, 0);
if (!port->membase)
/* No point of dev_err since UART itself is hosed here */
return -ENXIO;
port->irq = irq_of_parse_and_map(np, 0);
port->dev = &pdev->dev;
port->iotype = UPIO_MEM;
port->flags = UPF_BOOT_AUTOCONF;
port->line = dev_id;
port->ops = &arc_serial_pops;
port->fifosize = ARC_UART_TX_FIFO_SIZE;
/*
* uart_insert_char( ) uses it in decideding whether to ignore a
* char or not. Explicitly setting it here, removes the subtelty
*/
port->ignore_status_mask = 0;
return uart_add_one_port(&arc_uart_driver, &arc_uart_ports[dev_id].port);
}
static int arc_serial_remove(struct platform_device *pdev)
@ -732,27 +658,6 @@ static struct platform_driver arc_platform_driver = {
},
};
#ifdef CONFIG_SERIAL_ARC_CONSOLE
static struct platform_driver early_arc_platform_driver __initdata = {
.probe = arc_serial_probe_earlyprintk,
.remove = arc_serial_remove,
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
},
};
/*
* Register an early platform driver of "earlyprintk" class.
* ARCH platform code installs the driver and probes the early devices
* The installation could rely on user specifying earlyprintk=xyx in cmd line
* or it could be done independently, for all "earlyprintk" class drivers.
* [see arch/arc/plat-arcfpga/platform.c]
*/
early_platform_init("earlyprintk", &early_arc_platform_driver);
#endif /* CONFIG_SERIAL_ARC_CONSOLE */
static int __init arc_serial_init(void)
{
int ret;

View File

@ -706,7 +706,7 @@ static void atmel_release_tx_dma(struct uart_port *port)
dmaengine_terminate_all(chan);
dma_release_channel(chan);
dma_unmap_sg(port->dev, &atmel_port->sg_tx, 1,
DMA_MEM_TO_DEV);
DMA_TO_DEVICE);
}
atmel_port->desc_tx = NULL;
@ -804,7 +804,7 @@ static int atmel_prepare_tx_dma(struct uart_port *port)
nent = dma_map_sg(port->dev,
&atmel_port->sg_tx,
1,
DMA_MEM_TO_DEV);
DMA_TO_DEVICE);
if (!nent) {
dev_dbg(port->dev, "need to release resource of dma\n");
@ -883,7 +883,7 @@ static void atmel_release_rx_dma(struct uart_port *port)
dmaengine_terminate_all(chan);
dma_release_channel(chan);
dma_unmap_sg(port->dev, &atmel_port->sg_rx, 1,
DMA_DEV_TO_MEM);
DMA_FROM_DEVICE);
}
atmel_port->desc_rx = NULL;
@ -968,7 +968,7 @@ static int atmel_prepare_rx_dma(struct uart_port *port)
nent = dma_map_sg(port->dev,
&atmel_port->sg_rx,
1,
DMA_DEV_TO_MEM);
DMA_FROM_DEVICE);
if (!nent) {
dev_dbg(port->dev, "need to release resource of dma\n");

View File

@ -426,11 +426,6 @@ static void sport_stop_rx(struct uart_port *port)
SSYNC();
}
static void sport_enable_ms(struct uart_port *port)
{
pr_debug("%s enter\n", __func__);
}
static void sport_break_ctl(struct uart_port *port, int break_state)
{
pr_debug("%s enter\n", __func__);
@ -500,6 +495,13 @@ static void sport_set_termios(struct uart_port *port,
pr_debug("%s enter, c_cflag:%08x\n", __func__, termios->c_cflag);
#ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS
if (old == NULL && up->cts_pin != -1)
termios->c_cflag |= CRTSCTS;
else if (up->cts_pin == -1)
termios->c_cflag &= ~CRTSCTS;
#endif
switch (termios->c_cflag & CSIZE) {
case CS8:
up->csize = 8;
@ -587,7 +589,6 @@ struct uart_ops sport_uart_ops = {
.stop_tx = sport_stop_tx,
.start_tx = sport_start_tx,
.stop_rx = sport_stop_rx,
.enable_ms = sport_enable_ms,
.break_ctl = sport_break_ctl,
.startup = sport_startup,
.shutdown = sport_shutdown,
@ -813,10 +814,8 @@ static int sport_uart_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
if (res == NULL)
sport->cts_pin = -1;
else {
else
sport->cts_pin = res->start;
sport->port.flags |= ASYNC_CTS_FLOW;
}
res = platform_get_resource(pdev, IORESOURCE_IO, 1);
if (res == NULL)

View File

@ -200,14 +200,6 @@ static void bfin_serial_stop_rx(struct uart_port *port)
UART_CLEAR_IER(uart, ERBFI);
}
/*
* Set the modem control timer to fire immediately.
*/
static void bfin_serial_enable_ms(struct uart_port *port)
{
}
#if ANOMALY_05000363 && defined(CONFIG_SERIAL_BFIN_PIO)
# define UART_GET_ANOMALY_THRESHOLD(uart) ((uart)->anomaly_threshold)
# define UART_SET_ANOMALY_THRESHOLD(uart, v) ((uart)->anomaly_threshold = (v))
@ -793,6 +785,13 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
unsigned int ier, lcr = 0;
unsigned long timeout;
#ifdef CONFIG_SERIAL_BFIN_CTSRTS
if (old == NULL && uart->cts_pin != -1)
termios->c_cflag |= CRTSCTS;
else if (uart->cts_pin == -1)
termios->c_cflag &= ~CRTSCTS;
#endif
switch (termios->c_cflag & CSIZE) {
case CS8:
lcr = WLS(8);
@ -1014,7 +1013,6 @@ static struct uart_ops bfin_serial_pops = {
.stop_tx = bfin_serial_stop_tx,
.start_tx = bfin_serial_start_tx,
.stop_rx = bfin_serial_stop_rx,
.enable_ms = bfin_serial_enable_ms,
.break_ctl = bfin_serial_break_ctl,
.startup = bfin_serial_startup,
.shutdown = bfin_serial_shutdown,
@ -1325,12 +1323,8 @@ static int bfin_serial_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
if (res == NULL)
uart->cts_pin = -1;
else {
else
uart->cts_pin = res->start;
#ifdef CONFIG_SERIAL_BFIN_CTSRTS
uart->port.flags |= ASYNC_CTS_FLOW;
#endif
}
res = platform_get_resource(pdev, IORESOURCE_IO, 1);
if (res == NULL)

View File

@ -352,7 +352,6 @@ static const struct uart_ops uart_clps711x_ops = {
.stop_tx = uart_clps711x_stop_tx,
.start_tx = uart_clps711x_start_tx,
.stop_rx = uart_clps711x_nop_void,
.enable_ms = uart_clps711x_nop_void,
.break_ctl = uart_clps711x_break_ctl,
.set_ldisc = uart_clps711x_set_ldisc,
.startup = uart_clps711x_startup,

View File

@ -201,14 +201,6 @@ static void cpm_uart_stop_rx(struct uart_port *port)
clrbits16(&sccp->scc_sccm, UART_SCCM_RX);
}
/*
* Enable Modem status interrupts
*/
static void cpm_uart_enable_ms(struct uart_port *port)
{
pr_debug("CPM uart[%d]:enable ms\n", port->line);
}
/*
* Generate a break.
*/
@ -1122,7 +1114,6 @@ static struct uart_ops cpm_uart_pops = {
.stop_tx = cpm_uart_stop_tx,
.start_tx = cpm_uart_start_tx,
.stop_rx = cpm_uart_stop_rx,
.enable_ms = cpm_uart_enable_ms,
.break_ctl = cpm_uart_break_ctl,
.startup = cpm_uart_startup,
.shutdown = cpm_uart_shutdown,

View File

@ -3831,14 +3831,13 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
DECLARE_WAITQUEUE(wait, current);
unsigned long flags;
int retval;
int do_clocal = 0, extra_count = 0;
int do_clocal = 0;
/*
* If the device is in the middle of being closed, then block
* until it's done, and then try again.
*/
if (tty_hung_up_p(filp) ||
(info->port.flags & ASYNC_CLOSING)) {
if (info->port.flags & ASYNC_CLOSING) {
wait_event_interruptible_tty(tty, info->port.close_wait,
!(info->port.flags & ASYNC_CLOSING));
#ifdef SERIAL_DO_RESTART
@ -3879,10 +3878,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
info->line, info->port.count);
#endif
local_irq_save(flags);
if (!tty_hung_up_p(filp)) {
extra_count++;
info->port.count--;
}
info->port.count--;
local_irq_restore(flags);
info->port.blocked_open++;
while (1) {
@ -3921,7 +3917,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
}
set_current_state(TASK_RUNNING);
remove_wait_queue(&info->port.open_wait, &wait);
if (extra_count)
if (!tty_hung_up_p(filp))
info->port.count++;
info->port.blocked_open--;
#ifdef SERIAL_DEBUG_OPEN
@ -3976,8 +3972,7 @@ rs_open(struct tty_struct *tty, struct file * filp)
/*
* If the port is in the middle of closing, bail out now
*/
if (tty_hung_up_p(filp) ||
(info->port.flags & ASYNC_CLOSING)) {
if (info->port.flags & ASYNC_CLOSING) {
wait_event_interruptible_tty(tty, info->port.close_wait,
!(info->port.flags & ASYNC_CLOSING));
#ifdef SERIAL_DO_RESTART

View File

@ -151,11 +151,6 @@ static void dz_stop_rx(struct uart_port *uport)
dz_out(dport, DZ_LPR, dport->cflag);
}
static void dz_enable_ms(struct uart_port *uport)
{
/* nothing to do */
}
/*
* ------------------------------------------------------------
*
@ -751,7 +746,6 @@ static struct uart_ops dz_ops = {
.stop_tx = dz_stop_tx,
.start_tx = dz_start_tx,
.stop_rx = dz_stop_rx,
.enable_ms = dz_enable_ms,
.break_ctl = dz_break_ctl,
.startup = dz_startup,
.shutdown = dz_shutdown,

View File

@ -185,11 +185,6 @@ static void efm32_uart_stop_rx(struct uart_port *port)
efm32_uart_write32(efm_port, UARTn_CMD_RXDIS, UARTn_CMD);
}
static void efm32_uart_enable_ms(struct uart_port *port)
{
/* no handshake lines, no modem status interrupts */
}
static void efm32_uart_break_ctl(struct uart_port *port, int ctl)
{
/* not possible without fiddling with gpios */
@ -499,7 +494,6 @@ static struct uart_ops efm32_uart_pops = {
.stop_tx = efm32_uart_stop_tx,
.start_tx = efm32_uart_start_tx,
.stop_rx = efm32_uart_stop_rx,
.enable_ms = efm32_uart_enable_ms,
.break_ctl = efm32_uart_break_ctl,
.startup = efm32_uart_startup,
.shutdown = efm32_uart_shutdown,
@ -671,10 +665,16 @@ static int efm32_uart_probe_dt(struct platform_device *pdev,
if (!np)
return 1;
ret = of_property_read_u32(np, "efm32,location", &location);
ret = of_property_read_u32(np, "energymicro,location", &location);
if (ret)
/* fall back to wrongly namespaced property */
ret = of_property_read_u32(np, "efm32,location", &location);
if (ret)
/* fall back to old and (wrongly) generic property "location" */
ret = of_property_read_u32(np, "location", &location);
if (!ret) {
if (location > 5) {
dev_err(&pdev->dev, "invalid location\n");

View File

@ -1,7 +1,7 @@
/*
* Freescale lpuart serial port driver
*
* Copyright 2012-2013 Freescale Semiconductor, Inc.
* Copyright 2012-2014 Freescale Semiconductor, Inc.
*
* 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
@ -117,8 +117,113 @@
#define UARTSFIFO_TXOF 0x02
#define UARTSFIFO_RXUF 0x01
#define DMA_MAXBURST 16
#define DMA_MAXBURST_MASK (DMA_MAXBURST - 1)
/* 32-bit register defination */
#define UARTBAUD 0x00
#define UARTSTAT 0x04
#define UARTCTRL 0x08
#define UARTDATA 0x0C
#define UARTMATCH 0x10
#define UARTMODIR 0x14
#define UARTFIFO 0x18
#define UARTWATER 0x1c
#define UARTBAUD_MAEN1 0x80000000
#define UARTBAUD_MAEN2 0x40000000
#define UARTBAUD_M10 0x20000000
#define UARTBAUD_TDMAE 0x00800000
#define UARTBAUD_RDMAE 0x00200000
#define UARTBAUD_MATCFG 0x00400000
#define UARTBAUD_BOTHEDGE 0x00020000
#define UARTBAUD_RESYNCDIS 0x00010000
#define UARTBAUD_LBKDIE 0x00008000
#define UARTBAUD_RXEDGIE 0x00004000
#define UARTBAUD_SBNS 0x00002000
#define UARTBAUD_SBR 0x00000000
#define UARTBAUD_SBR_MASK 0x1fff
#define UARTSTAT_LBKDIF 0x80000000
#define UARTSTAT_RXEDGIF 0x40000000
#define UARTSTAT_MSBF 0x20000000
#define UARTSTAT_RXINV 0x10000000
#define UARTSTAT_RWUID 0x08000000
#define UARTSTAT_BRK13 0x04000000
#define UARTSTAT_LBKDE 0x02000000
#define UARTSTAT_RAF 0x01000000
#define UARTSTAT_TDRE 0x00800000
#define UARTSTAT_TC 0x00400000
#define UARTSTAT_RDRF 0x00200000
#define UARTSTAT_IDLE 0x00100000
#define UARTSTAT_OR 0x00080000
#define UARTSTAT_NF 0x00040000
#define UARTSTAT_FE 0x00020000
#define UARTSTAT_PE 0x00010000
#define UARTSTAT_MA1F 0x00008000
#define UARTSTAT_M21F 0x00004000
#define UARTCTRL_R8T9 0x80000000
#define UARTCTRL_R9T8 0x40000000
#define UARTCTRL_TXDIR 0x20000000
#define UARTCTRL_TXINV 0x10000000
#define UARTCTRL_ORIE 0x08000000
#define UARTCTRL_NEIE 0x04000000
#define UARTCTRL_FEIE 0x02000000
#define UARTCTRL_PEIE 0x01000000
#define UARTCTRL_TIE 0x00800000
#define UARTCTRL_TCIE 0x00400000
#define UARTCTRL_RIE 0x00200000
#define UARTCTRL_ILIE 0x00100000
#define UARTCTRL_TE 0x00080000
#define UARTCTRL_RE 0x00040000
#define UARTCTRL_RWU 0x00020000
#define UARTCTRL_SBK 0x00010000
#define UARTCTRL_MA1IE 0x00008000
#define UARTCTRL_MA2IE 0x00004000
#define UARTCTRL_IDLECFG 0x00000100
#define UARTCTRL_LOOPS 0x00000080
#define UARTCTRL_DOZEEN 0x00000040
#define UARTCTRL_RSRC 0x00000020
#define UARTCTRL_M 0x00000010
#define UARTCTRL_WAKE 0x00000008
#define UARTCTRL_ILT 0x00000004
#define UARTCTRL_PE 0x00000002
#define UARTCTRL_PT 0x00000001
#define UARTDATA_NOISY 0x00008000
#define UARTDATA_PARITYE 0x00004000
#define UARTDATA_FRETSC 0x00002000
#define UARTDATA_RXEMPT 0x00001000
#define UARTDATA_IDLINE 0x00000800
#define UARTDATA_MASK 0x3ff
#define UARTMODIR_IREN 0x00020000
#define UARTMODIR_TXCTSSRC 0x00000020
#define UARTMODIR_TXCTSC 0x00000010
#define UARTMODIR_RXRTSE 0x00000008
#define UARTMODIR_TXRTSPOL 0x00000004
#define UARTMODIR_TXRTSE 0x00000002
#define UARTMODIR_TXCTSE 0x00000001
#define UARTFIFO_TXEMPT 0x00800000
#define UARTFIFO_RXEMPT 0x00400000
#define UARTFIFO_TXOF 0x00020000
#define UARTFIFO_RXUF 0x00010000
#define UARTFIFO_TXFLUSH 0x00008000
#define UARTFIFO_RXFLUSH 0x00004000
#define UARTFIFO_TXOFE 0x00000200
#define UARTFIFO_RXUFE 0x00000100
#define UARTFIFO_TXFE 0x00000080
#define UARTFIFO_FIFOSIZE_MASK 0x7
#define UARTFIFO_TXSIZE_OFF 4
#define UARTFIFO_RXFE 0x00000008
#define UARTFIFO_RXSIZE_OFF 0
#define UARTWATER_COUNT_MASK 0xff
#define UARTWATER_TXCNT_OFF 8
#define UARTWATER_RXCNT_OFF 24
#define UARTWATER_WATER_MASK 0xff
#define UARTWATER_TXWATER_OFF 0
#define UARTWATER_RXWATER_OFF 16
#define FSL_UART_RX_DMA_BUFFER_SIZE 64
#define DRIVER_NAME "fsl-lpuart"
@ -130,6 +235,7 @@ struct lpuart_port {
struct clk *clk;
unsigned int txfifo_size;
unsigned int rxfifo_size;
bool lpuart32;
bool lpuart_dma_use;
struct dma_chan *dma_tx_chan;
@ -154,6 +260,9 @@ static struct of_device_id lpuart_dt_ids[] = {
{
.compatible = "fsl,vf610-lpuart",
},
{
.compatible = "fsl,ls1021a-lpuart",
},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, lpuart_dt_ids);
@ -162,6 +271,16 @@ MODULE_DEVICE_TABLE(of, lpuart_dt_ids);
static void lpuart_dma_tx_complete(void *arg);
static void lpuart_dma_rx_complete(void *arg);
static u32 lpuart32_read(void __iomem *addr)
{
return ioread32be(addr);
}
static void lpuart32_write(u32 val, void __iomem *addr)
{
iowrite32be(val, addr);
}
static void lpuart_stop_tx(struct uart_port *port)
{
unsigned char temp;
@ -171,6 +290,15 @@ static void lpuart_stop_tx(struct uart_port *port)
writeb(temp, port->membase + UARTCR2);
}
static void lpuart32_stop_tx(struct uart_port *port)
{
unsigned long temp;
temp = lpuart32_read(port->membase + UARTCTRL);
temp &= ~(UARTCTRL_TIE | UARTCTRL_TCIE);
lpuart32_write(temp, port->membase + UARTCTRL);
}
static void lpuart_stop_rx(struct uart_port *port)
{
unsigned char temp;
@ -179,8 +307,12 @@ static void lpuart_stop_rx(struct uart_port *port)
writeb(temp & ~UARTCR2_RE, port->membase + UARTCR2);
}
static void lpuart_enable_ms(struct uart_port *port)
static void lpuart32_stop_rx(struct uart_port *port)
{
unsigned long temp;
temp = lpuart32_read(port->membase + UARTCTRL);
lpuart32_write(temp & ~UARTCTRL_RE, port->membase + UARTCTRL);
}
static void lpuart_copy_rx_to_tty(struct lpuart_port *sport,
@ -240,7 +372,7 @@ static int lpuart_dma_tx(struct lpuart_port *sport, unsigned long count)
dma_sync_single_for_device(sport->port.dev, sport->dma_tx_buf_bus,
UART_XMIT_SIZE, DMA_TO_DEVICE);
sport->dma_tx_bytes = count & ~(DMA_MAXBURST_MASK);
sport->dma_tx_bytes = count & ~(sport->txfifo_size - 1);
tx_bus_addr = sport->dma_tx_buf_bus + xmit->tail;
sport->dma_tx_desc = dmaengine_prep_slave_single(sport->dma_tx_chan,
tx_bus_addr, sport->dma_tx_bytes,
@ -269,7 +401,7 @@ static void lpuart_prepare_tx(struct lpuart_port *sport)
if (!count)
return;
if (count < DMA_MAXBURST)
if (count < sport->txfifo_size)
writeb(readb(sport->port.membase + UARTCR5) & ~UARTCR5_TDMAS,
sport->port.membase + UARTCR5);
else {
@ -405,6 +537,30 @@ static inline void lpuart_transmit_buffer(struct lpuart_port *sport)
lpuart_stop_tx(&sport->port);
}
static inline void lpuart32_transmit_buffer(struct lpuart_port *sport)
{
struct circ_buf *xmit = &sport->port.state->xmit;
unsigned long txcnt;
txcnt = lpuart32_read(sport->port.membase + UARTWATER);
txcnt = txcnt >> UARTWATER_TXCNT_OFF;
txcnt &= UARTWATER_COUNT_MASK;
while (!uart_circ_empty(xmit) && (txcnt < sport->txfifo_size)) {
lpuart32_write(xmit->buf[xmit->tail], sport->port.membase + UARTDATA);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
sport->port.icount.tx++;
txcnt = lpuart32_read(sport->port.membase + UARTWATER);
txcnt = txcnt >> UARTWATER_TXCNT_OFF;
txcnt &= UARTWATER_COUNT_MASK;
}
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(&sport->port);
if (uart_circ_empty(xmit))
lpuart32_stop_tx(&sport->port);
}
static void lpuart_start_tx(struct uart_port *port)
{
struct lpuart_port *sport = container_of(port,
@ -424,6 +580,18 @@ static void lpuart_start_tx(struct uart_port *port)
}
}
static void lpuart32_start_tx(struct uart_port *port)
{
struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
unsigned long temp;
temp = lpuart32_read(port->membase + UARTCTRL);
lpuart32_write(temp | UARTCTRL_TIE, port->membase + UARTCTRL);
if (lpuart32_read(port->membase + UARTSTAT) & UARTSTAT_TDRE)
lpuart32_transmit_buffer(sport);
}
static irqreturn_t lpuart_txint(int irq, void *dev_id)
{
struct lpuart_port *sport = dev_id;
@ -432,16 +600,25 @@ static irqreturn_t lpuart_txint(int irq, void *dev_id)
spin_lock_irqsave(&sport->port.lock, flags);
if (sport->port.x_char) {
writeb(sport->port.x_char, sport->port.membase + UARTDR);
if (sport->lpuart32)
lpuart32_write(sport->port.x_char, sport->port.membase + UARTDATA);
else
writeb(sport->port.x_char, sport->port.membase + UARTDR);
goto out;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
lpuart_stop_tx(&sport->port);
if (sport->lpuart32)
lpuart32_stop_tx(&sport->port);
else
lpuart_stop_tx(&sport->port);
goto out;
}
lpuart_transmit_buffer(sport);
if (sport->lpuart32)
lpuart32_transmit_buffer(sport);
else
lpuart_transmit_buffer(sport);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(&sport->port);
@ -514,6 +691,70 @@ out:
return IRQ_HANDLED;
}
static irqreturn_t lpuart32_rxint(int irq, void *dev_id)
{
struct lpuart_port *sport = dev_id;
unsigned int flg, ignored = 0;
struct tty_port *port = &sport->port.state->port;
unsigned long flags;
unsigned long rx, sr;
spin_lock_irqsave(&sport->port.lock, flags);
while (!(lpuart32_read(sport->port.membase + UARTFIFO) & UARTFIFO_RXEMPT)) {
flg = TTY_NORMAL;
sport->port.icount.rx++;
/*
* to clear the FE, OR, NF, FE, PE flags,
* read STAT then read DATA reg
*/
sr = lpuart32_read(sport->port.membase + UARTSTAT);
rx = lpuart32_read(sport->port.membase + UARTDATA);
rx &= 0x3ff;
if (uart_handle_sysrq_char(&sport->port, (unsigned char)rx))
continue;
if (sr & (UARTSTAT_PE | UARTSTAT_OR | UARTSTAT_FE)) {
if (sr & UARTSTAT_PE)
sport->port.icount.parity++;
else if (sr & UARTSTAT_FE)
sport->port.icount.frame++;
if (sr & UARTSTAT_OR)
sport->port.icount.overrun++;
if (sr & sport->port.ignore_status_mask) {
if (++ignored > 100)
goto out;
continue;
}
sr &= sport->port.read_status_mask;
if (sr & UARTSTAT_PE)
flg = TTY_PARITY;
else if (sr & UARTSTAT_FE)
flg = TTY_FRAME;
if (sr & UARTSTAT_OR)
flg = TTY_OVERRUN;
#ifdef SUPPORT_SYSRQ
sport->port.sysrq = 0;
#endif
}
tty_insert_flip_char(port, rx, flg);
}
out:
spin_unlock_irqrestore(&sport->port.lock, flags);
tty_flip_buffer_push(port);
return IRQ_HANDLED;
}
static irqreturn_t lpuart_int(int irq, void *dev_id)
{
struct lpuart_port *sport = dev_id;
@ -538,6 +779,26 @@ static irqreturn_t lpuart_int(int irq, void *dev_id)
return IRQ_HANDLED;
}
static irqreturn_t lpuart32_int(int irq, void *dev_id)
{
struct lpuart_port *sport = dev_id;
unsigned long sts, rxcount;
sts = lpuart32_read(sport->port.membase + UARTSTAT);
rxcount = lpuart32_read(sport->port.membase + UARTWATER);
rxcount = rxcount >> UARTWATER_RXCNT_OFF;
if (sts & UARTSTAT_RDRF || rxcount > 0)
lpuart32_rxint(irq, dev_id);
if ((sts & UARTSTAT_TDRE) &&
!(lpuart32_read(sport->port.membase + UARTBAUD) & UARTBAUD_TDMAE))
lpuart_txint(irq, dev_id);
lpuart32_write(sts, sport->port.membase + UARTSTAT);
return IRQ_HANDLED;
}
/* return TIOCSER_TEMT when transmitter is not busy */
static unsigned int lpuart_tx_empty(struct uart_port *port)
{
@ -545,6 +806,12 @@ static unsigned int lpuart_tx_empty(struct uart_port *port)
TIOCSER_TEMT : 0;
}
static unsigned int lpuart32_tx_empty(struct uart_port *port)
{
return (lpuart32_read(port->membase + UARTSTAT) & UARTSTAT_TC) ?
TIOCSER_TEMT : 0;
}
static unsigned int lpuart_get_mctrl(struct uart_port *port)
{
unsigned int temp = 0;
@ -560,6 +827,21 @@ static unsigned int lpuart_get_mctrl(struct uart_port *port)
return temp;
}
static unsigned int lpuart32_get_mctrl(struct uart_port *port)
{
unsigned int temp = 0;
unsigned long reg;
reg = lpuart32_read(port->membase + UARTMODIR);
if (reg & UARTMODIR_TXCTSE)
temp |= TIOCM_CTS;
if (reg & UARTMODIR_RXRTSE)
temp |= TIOCM_RTS;
return temp;
}
static void lpuart_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
unsigned char temp;
@ -576,6 +858,22 @@ static void lpuart_set_mctrl(struct uart_port *port, unsigned int mctrl)
writeb(temp, port->membase + UARTMODEM);
}
static void lpuart32_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
unsigned long temp;
temp = lpuart32_read(port->membase + UARTMODIR) &
~(UARTMODIR_RXRTSE | UARTMODIR_TXCTSE);
if (mctrl & TIOCM_RTS)
temp |= UARTMODIR_RXRTSE;
if (mctrl & TIOCM_CTS)
temp |= UARTMODIR_TXCTSE;
lpuart32_write(temp, port->membase + UARTMODIR);
}
static void lpuart_break_ctl(struct uart_port *port, int break_state)
{
unsigned char temp;
@ -588,6 +886,18 @@ static void lpuart_break_ctl(struct uart_port *port, int break_state)
writeb(temp, port->membase + UARTCR2);
}
static void lpuart32_break_ctl(struct uart_port *port, int break_state)
{
unsigned long temp;
temp = lpuart32_read(port->membase + UARTCTRL) & ~UARTCTRL_SBK;
if (break_state != 0)
temp |= UARTCTRL_SBK;
lpuart32_write(temp, port->membase + UARTCTRL);
}
static void lpuart_setup_watermark(struct lpuart_port *sport)
{
unsigned char val, cr2;
@ -599,15 +909,7 @@ static void lpuart_setup_watermark(struct lpuart_port *sport)
UARTCR2_RIE | UARTCR2_RE);
writeb(cr2, sport->port.membase + UARTCR2);
/* determine FIFO size and enable FIFO mode */
val = readb(sport->port.membase + UARTPFIFO);
sport->txfifo_size = 0x1 << (((val >> UARTPFIFO_TXSIZE_OFF) &
UARTPFIFO_FIFOSIZE_MASK) + 1);
sport->rxfifo_size = 0x1 << (((val >> UARTPFIFO_RXSIZE_OFF) &
UARTPFIFO_FIFOSIZE_MASK) + 1);
writeb(val | UARTPFIFO_TXFE | UARTPFIFO_RXFE,
sport->port.membase + UARTPFIFO);
@ -622,6 +924,31 @@ static void lpuart_setup_watermark(struct lpuart_port *sport)
writeb(cr2_saved, sport->port.membase + UARTCR2);
}
static void lpuart32_setup_watermark(struct lpuart_port *sport)
{
unsigned long val, ctrl;
unsigned long ctrl_saved;
ctrl = lpuart32_read(sport->port.membase + UARTCTRL);
ctrl_saved = ctrl;
ctrl &= ~(UARTCTRL_TIE | UARTCTRL_TCIE | UARTCTRL_TE |
UARTCTRL_RIE | UARTCTRL_RE);
lpuart32_write(ctrl, sport->port.membase + UARTCTRL);
/* enable FIFO mode */
val = lpuart32_read(sport->port.membase + UARTFIFO);
val |= UARTFIFO_TXFE | UARTFIFO_RXFE;
val |= UARTFIFO_TXFLUSH | UARTFIFO_RXFLUSH;
lpuart32_write(val, sport->port.membase + UARTFIFO);
/* set the watermark */
val = (0x1 << UARTWATER_RXWATER_OFF) | (0x0 << UARTWATER_TXWATER_OFF);
lpuart32_write(val, sport->port.membase + UARTWATER);
/* Restore cr2 */
lpuart32_write(ctrl_saved, sport->port.membase + UARTCTRL);
}
static int lpuart_dma_tx_request(struct uart_port *port)
{
struct lpuart_port *sport = container_of(port,
@ -652,7 +979,7 @@ static int lpuart_dma_tx_request(struct uart_port *port)
dma_buf = sport->port.state->xmit.buf;
dma_tx_sconfig.dst_addr = sport->port.mapbase + UARTDR;
dma_tx_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
dma_tx_sconfig.dst_maxburst = DMA_MAXBURST;
dma_tx_sconfig.dst_maxburst = sport->txfifo_size;
dma_tx_sconfig.direction = DMA_MEM_TO_DEV;
ret = dmaengine_slave_config(tx_chan, &dma_tx_sconfig);
@ -724,13 +1051,6 @@ static int lpuart_dma_rx_request(struct uart_port *port)
sport->dma_rx_buf_bus = dma_bus;
sport->dma_rx_in_progress = 0;
sport->dma_rx_timeout = (sport->port.timeout - HZ / 50) *
FSL_UART_RX_DMA_BUFFER_SIZE * 3 /
sport->rxfifo_size / 2;
if (sport->dma_rx_timeout < msecs_to_jiffies(20))
sport->dma_rx_timeout = msecs_to_jiffies(20);
return 0;
}
@ -772,7 +1092,16 @@ static int lpuart_startup(struct uart_port *port)
unsigned long flags;
unsigned char temp;
/*whether use dma support by dma request results*/
/* determine FIFO size and enable FIFO mode */
temp = readb(sport->port.membase + UARTPFIFO);
sport->txfifo_size = 0x1 << (((temp >> UARTPFIFO_TXSIZE_OFF) &
UARTPFIFO_FIFOSIZE_MASK) + 1);
sport->rxfifo_size = 0x1 << (((temp >> UARTPFIFO_RXSIZE_OFF) &
UARTPFIFO_FIFOSIZE_MASK) + 1);
/* Whether use dma support by dma request results */
if (lpuart_dma_tx_request(port) || lpuart_dma_rx_request(port)) {
sport->lpuart_dma_use = false;
} else {
@ -798,6 +1127,40 @@ static int lpuart_startup(struct uart_port *port)
return 0;
}
static int lpuart32_startup(struct uart_port *port)
{
struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
int ret;
unsigned long flags;
unsigned long temp;
/* determine FIFO size */
temp = lpuart32_read(sport->port.membase + UARTFIFO);
sport->txfifo_size = 0x1 << (((temp >> UARTFIFO_TXSIZE_OFF) &
UARTFIFO_FIFOSIZE_MASK) - 1);
sport->rxfifo_size = 0x1 << (((temp >> UARTFIFO_RXSIZE_OFF) &
UARTFIFO_FIFOSIZE_MASK) - 1);
ret = devm_request_irq(port->dev, port->irq, lpuart32_int, 0,
DRIVER_NAME, sport);
if (ret)
return ret;
spin_lock_irqsave(&sport->port.lock, flags);
lpuart32_setup_watermark(sport);
temp = lpuart32_read(sport->port.membase + UARTCTRL);
temp |= (UARTCTRL_RIE | UARTCTRL_TIE | UARTCTRL_RE | UARTCTRL_TE);
temp |= UARTCTRL_ILIE;
lpuart32_write(temp, sport->port.membase + UARTCTRL);
spin_unlock_irqrestore(&sport->port.lock, flags);
return 0;
}
static void lpuart_shutdown(struct uart_port *port)
{
struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
@ -822,6 +1185,25 @@ static void lpuart_shutdown(struct uart_port *port)
}
}
static void lpuart32_shutdown(struct uart_port *port)
{
struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
unsigned long temp;
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
/* disable Rx/Tx and interrupts */
temp = lpuart32_read(port->membase + UARTCTRL);
temp &= ~(UARTCTRL_TE | UARTCTRL_RE |
UARTCTRL_TIE | UARTCTRL_TCIE | UARTCTRL_RIE);
lpuart32_write(temp, port->membase + UARTCTRL);
spin_unlock_irqrestore(&port->lock, flags);
devm_free_irq(port->dev, port->irq, sport);
}
static void
lpuart_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old)
@ -922,6 +1304,17 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios,
/* update the per-port timeout */
uart_update_timeout(port, termios->c_cflag, baud);
if (sport->lpuart_dma_use) {
/* Calculate delay for 1.5 DMA buffers */
sport->dma_rx_timeout = (sport->port.timeout - HZ / 50) *
FSL_UART_RX_DMA_BUFFER_SIZE * 3 /
sport->rxfifo_size / 2;
dev_dbg(port->dev, "DMA Rx t-out %ums, tty t-out %u jiffies\n",
sport->dma_rx_timeout * 1000 / HZ, sport->port.timeout);
if (sport->dma_rx_timeout < msecs_to_jiffies(20))
sport->dma_rx_timeout = msecs_to_jiffies(20);
}
/* wait transmit engin complete */
while (!(readb(sport->port.membase + UARTSR1) & UARTSR1_TC))
barrier();
@ -948,6 +1341,125 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios,
spin_unlock_irqrestore(&sport->port.lock, flags);
}
static void
lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old)
{
struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
unsigned long flags;
unsigned long ctrl, old_ctrl, bd, modem;
unsigned int baud;
unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
unsigned int sbr;
ctrl = old_ctrl = lpuart32_read(sport->port.membase + UARTCTRL);
bd = lpuart32_read(sport->port.membase + UARTBAUD);
modem = lpuart32_read(sport->port.membase + UARTMODIR);
/*
* only support CS8 and CS7, and for CS7 must enable PE.
* supported mode:
* - (7,e/o,1)
* - (8,n,1)
* - (8,m/s,1)
* - (8,e/o,1)
*/
while ((termios->c_cflag & CSIZE) != CS8 &&
(termios->c_cflag & CSIZE) != CS7) {
termios->c_cflag &= ~CSIZE;
termios->c_cflag |= old_csize;
old_csize = CS8;
}
if ((termios->c_cflag & CSIZE) == CS8 ||
(termios->c_cflag & CSIZE) == CS7)
ctrl = old_ctrl & ~UARTCTRL_M;
if (termios->c_cflag & CMSPAR) {
if ((termios->c_cflag & CSIZE) != CS8) {
termios->c_cflag &= ~CSIZE;
termios->c_cflag |= CS8;
}
ctrl |= UARTCTRL_M;
}
if (termios->c_cflag & CRTSCTS) {
modem |= (UARTMODEM_RXRTSE | UARTMODEM_TXCTSE);
} else {
termios->c_cflag &= ~CRTSCTS;
modem &= ~(UARTMODEM_RXRTSE | UARTMODEM_TXCTSE);
}
if (termios->c_cflag & CSTOPB)
termios->c_cflag &= ~CSTOPB;
/* parity must be enabled when CS7 to match 8-bits format */
if ((termios->c_cflag & CSIZE) == CS7)
termios->c_cflag |= PARENB;
if ((termios->c_cflag & PARENB)) {
if (termios->c_cflag & CMSPAR) {
ctrl &= ~UARTCTRL_PE;
ctrl |= UARTCTRL_M;
} else {
ctrl |= UARTCR1_PE;
if ((termios->c_cflag & CSIZE) == CS8)
ctrl |= UARTCTRL_M;
if (termios->c_cflag & PARODD)
ctrl |= UARTCTRL_PT;
else
ctrl &= ~UARTCTRL_PT;
}
}
/* ask the core to calculate the divisor */
baud = uart_get_baud_rate(port, termios, old, 50, port->uartclk / 16);
spin_lock_irqsave(&sport->port.lock, flags);
sport->port.read_status_mask = 0;
if (termios->c_iflag & INPCK)
sport->port.read_status_mask |= (UARTSTAT_FE | UARTSTAT_PE);
if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
sport->port.read_status_mask |= UARTSTAT_FE;
/* characters to ignore */
sport->port.ignore_status_mask = 0;
if (termios->c_iflag & IGNPAR)
sport->port.ignore_status_mask |= UARTSTAT_PE;
if (termios->c_iflag & IGNBRK) {
sport->port.ignore_status_mask |= UARTSTAT_FE;
/*
* if we're ignoring parity and break indicators,
* ignore overruns too (for real raw support).
*/
if (termios->c_iflag & IGNPAR)
sport->port.ignore_status_mask |= UARTSTAT_OR;
}
/* update the per-port timeout */
uart_update_timeout(port, termios->c_cflag, baud);
/* wait transmit engin complete */
while (!(lpuart32_read(sport->port.membase + UARTSTAT) & UARTSTAT_TC))
barrier();
/* disable transmit and receive */
lpuart32_write(old_ctrl & ~(UARTCTRL_TE | UARTCTRL_RE),
sport->port.membase + UARTCTRL);
sbr = sport->port.uartclk / (16 * baud);
bd &= ~UARTBAUD_SBR_MASK;
bd |= sbr & UARTBAUD_SBR_MASK;
bd |= UARTBAUD_BOTHEDGE;
bd &= ~(UARTBAUD_TDMAE | UARTBAUD_RDMAE);
lpuart32_write(bd, sport->port.membase + UARTBAUD);
lpuart32_write(modem, sport->port.membase + UARTMODIR);
lpuart32_write(ctrl, sport->port.membase + UARTCTRL);
/* restore control register */
spin_unlock_irqrestore(&sport->port.lock, flags);
}
static const char *lpuart_type(struct uart_port *port)
{
return "FSL_LPUART";
@ -996,7 +1508,6 @@ static struct uart_ops lpuart_pops = {
.stop_tx = lpuart_stop_tx,
.start_tx = lpuart_start_tx,
.stop_rx = lpuart_stop_rx,
.enable_ms = lpuart_enable_ms,
.break_ctl = lpuart_break_ctl,
.startup = lpuart_startup,
.shutdown = lpuart_shutdown,
@ -1008,6 +1519,24 @@ static struct uart_ops lpuart_pops = {
.verify_port = lpuart_verify_port,
};
static struct uart_ops lpuart32_pops = {
.tx_empty = lpuart32_tx_empty,
.set_mctrl = lpuart32_set_mctrl,
.get_mctrl = lpuart32_get_mctrl,
.stop_tx = lpuart32_stop_tx,
.start_tx = lpuart32_start_tx,
.stop_rx = lpuart32_stop_rx,
.break_ctl = lpuart32_break_ctl,
.startup = lpuart32_startup,
.shutdown = lpuart32_shutdown,
.set_termios = lpuart32_set_termios,
.type = lpuart_type,
.request_port = lpuart_request_port,
.release_port = lpuart_release_port,
.config_port = lpuart_config_port,
.verify_port = lpuart_verify_port,
};
static struct lpuart_port *lpuart_ports[UART_NR];
#ifdef CONFIG_SERIAL_FSL_LPUART_CONSOLE
@ -1019,6 +1548,14 @@ static void lpuart_console_putchar(struct uart_port *port, int ch)
writeb(ch, port->membase + UARTDR);
}
static void lpuart32_console_putchar(struct uart_port *port, int ch)
{
while (!(lpuart32_read(port->membase + UARTSTAT) & UARTSTAT_TDRE))
barrier();
lpuart32_write(ch, port->membase + UARTDATA);
}
static void
lpuart_console_write(struct console *co, const char *s, unsigned int count)
{
@ -1040,6 +1577,27 @@ lpuart_console_write(struct console *co, const char *s, unsigned int count)
writeb(old_cr2, sport->port.membase + UARTCR2);
}
static void
lpuart32_console_write(struct console *co, const char *s, unsigned int count)
{
struct lpuart_port *sport = lpuart_ports[co->index];
unsigned long old_cr, cr;
/* first save CR2 and then disable interrupts */
cr = old_cr = lpuart32_read(sport->port.membase + UARTCTRL);
cr |= (UARTCTRL_TE | UARTCTRL_RE);
cr &= ~(UARTCTRL_TIE | UARTCTRL_TCIE | UARTCTRL_RIE);
lpuart32_write(cr, sport->port.membase + UARTCTRL);
uart_console_write(&sport->port, s, count, lpuart32_console_putchar);
/* wait for transmitter finish complete and restore CR2 */
while (!(lpuart32_read(sport->port.membase + UARTSTAT) & UARTSTAT_TC))
barrier();
lpuart32_write(old_cr, sport->port.membase + UARTCTRL);
}
/*
* if the port was already initialised (eg, by a boot loader),
* try to determine the current setup.
@ -1093,6 +1651,49 @@ lpuart_console_get_options(struct lpuart_port *sport, int *baud,
"from %d to %d\n", baud_raw, *baud);
}
static void __init
lpuart32_console_get_options(struct lpuart_port *sport, int *baud,
int *parity, int *bits)
{
unsigned long cr, bd;
unsigned int sbr, uartclk, baud_raw;
cr = lpuart32_read(sport->port.membase + UARTCTRL);
cr &= UARTCTRL_TE | UARTCTRL_RE;
if (!cr)
return;
/* ok, the port was enabled */
cr = lpuart32_read(sport->port.membase + UARTCTRL);
*parity = 'n';
if (cr & UARTCTRL_PE) {
if (cr & UARTCTRL_PT)
*parity = 'o';
else
*parity = 'e';
}
if (cr & UARTCTRL_M)
*bits = 9;
else
*bits = 8;
bd = lpuart32_read(sport->port.membase + UARTBAUD);
bd &= UARTBAUD_SBR_MASK;
sbr = bd;
uartclk = clk_get_rate(sport->clk);
/*
* baud = mod_clk/(16*(sbr[13]+(brfa)/32)
*/
baud_raw = uartclk / (16 * sbr);
if (*baud != baud_raw)
printk(KERN_INFO "Serial: Console lpuart rounded baud rate"
"from %d to %d\n", baud_raw, *baud);
}
static int __init lpuart_console_setup(struct console *co, char *options)
{
struct lpuart_port *sport;
@ -1116,9 +1717,15 @@ static int __init lpuart_console_setup(struct console *co, char *options)
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
else
lpuart_console_get_options(sport, &baud, &parity, &bits);
if (sport->lpuart32)
lpuart32_console_get_options(sport, &baud, &parity, &bits);
else
lpuart_console_get_options(sport, &baud, &parity, &bits);
lpuart_setup_watermark(sport);
if (sport->lpuart32)
lpuart32_setup_watermark(sport);
else
lpuart_setup_watermark(sport);
return uart_set_options(&sport->port, co, baud, parity, bits, flow);
}
@ -1134,9 +1741,21 @@ static struct console lpuart_console = {
.data = &lpuart_reg,
};
static struct console lpuart32_console = {
.name = DEV_NAME,
.write = lpuart32_console_write,
.device = uart_console_device,
.setup = lpuart_console_setup,
.flags = CON_PRINTBUFFER,
.index = -1,
.data = &lpuart_reg,
};
#define LPUART_CONSOLE (&lpuart_console)
#define LPUART32_CONSOLE (&lpuart32_console)
#else
#define LPUART_CONSOLE NULL
#define LPUART32_CONSOLE NULL
#endif
static struct uart_driver lpuart_reg = {
@ -1166,7 +1785,7 @@ static int lpuart_probe(struct platform_device *pdev)
return ret;
}
sport->port.line = ret;
sport->lpuart32 = of_device_is_compatible(np, "fsl,ls1021a-lpuart");
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENODEV;
@ -1180,7 +1799,10 @@ static int lpuart_probe(struct platform_device *pdev)
sport->port.type = PORT_LPUART;
sport->port.iotype = UPIO_MEM;
sport->port.irq = platform_get_irq(pdev, 0);
sport->port.ops = &lpuart_pops;
if (sport->lpuart32)
sport->port.ops = &lpuart32_pops;
else
sport->port.ops = &lpuart_pops;
sport->port.flags = UPF_BOOT_AUTOCONF;
sport->clk = devm_clk_get(&pdev->dev, "ipg");
@ -1202,6 +1824,11 @@ static int lpuart_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, &sport->port);
if (sport->lpuart32)
lpuart_reg.cons = LPUART32_CONSOLE;
else
lpuart_reg.cons = LPUART_CONSOLE;
ret = uart_add_one_port(&lpuart_reg, &sport->port);
if (ret) {
clk_disable_unprepare(sport->clk);

View File

@ -1052,11 +1052,6 @@ static void icom_stop_rx(struct uart_port *port)
writeb(cmdReg & ~CMD_RCV_ENABLE, &ICOM_PORT->dram->CmdReg);
}
static void icom_enable_ms(struct uart_port *port)
{
/* no-op */
}
static void icom_break(struct uart_port *port, int break_state)
{
unsigned char cmdReg;
@ -1300,7 +1295,6 @@ static struct uart_ops icom_ops = {
.start_tx = icom_start_tx,
.send_xchar = icom_send_xchar,
.stop_rx = icom_stop_rx,
.enable_ms = icom_enable_ms,
.break_ctl = icom_break,
.startup = icom_open,
.shutdown = icom_close,

View File

@ -1880,7 +1880,6 @@ static struct uart_ops ioc3_ops = {
.stop_tx = ic3_stop_tx,
.start_tx = ic3_start_tx,
.stop_rx = ic3_stop_rx,
.enable_ms = null_void_function,
.break_ctl = ic3_break_ctl,
.startup = ic3_startup,
.shutdown = ic3_shutdown,

View File

@ -2597,7 +2597,6 @@ static struct uart_ops ioc4_ops = {
.stop_tx = ic4_stop_tx,
.start_tx = ic4_start_tx,
.stop_rx = null_void_function,
.enable_ms = null_void_function,
.break_ctl = ic4_break_ctl,
.startup = ic4_startup,
.shutdown = ic4_shutdown,

View File

@ -177,11 +177,6 @@ static void jsm_tty_stop_rx(struct uart_port *port)
channel->ch_bd->bd_ops->disable_receiver(channel);
}
static void jsm_tty_enable_ms(struct uart_port *port)
{
/* Nothing needed */
}
static void jsm_tty_break(struct uart_port *port, int break_state)
{
unsigned long lock_flags;
@ -354,7 +349,6 @@ static struct uart_ops jsm_ops = {
.start_tx = jsm_tty_start_tx,
.send_xchar = jsm_tty_send_xchar,
.stop_rx = jsm_tty_stop_rx,
.enable_ms = jsm_tty_enable_ms,
.break_ctl = jsm_tty_break,
.startup = jsm_tty_open,
.shutdown = jsm_tty_close,

View File

@ -42,7 +42,7 @@ static char *kgdb_nmi_magic = "$3#33";
module_param_named(magic, kgdb_nmi_magic, charp, 0600);
MODULE_PARM_DESC(magic, "magic sequence to enter NMI debugger (default $3#33)");
static bool kgdb_nmi_tty_enabled;
static atomic_t kgdb_nmi_num_readers = ATOMIC_INIT(0);
static int kgdb_nmi_console_setup(struct console *co, char *options)
{
@ -136,7 +136,7 @@ static int kgdb_nmi_poll_one_knock(void)
n = 0;
}
if (kgdb_nmi_tty_enabled) {
if (atomic_read(&kgdb_nmi_num_readers)) {
kgdb_tty_recv(c);
return 0;
}
@ -197,7 +197,8 @@ static void kgdb_nmi_tty_receiver(unsigned long data)
priv->timer.expires = jiffies + (HZ/100);
add_timer(&priv->timer);
if (likely(!kgdb_nmi_tty_enabled || !kfifo_len(&priv->fifo)))
if (likely(!atomic_read(&kgdb_nmi_num_readers) ||
!kfifo_len(&priv->fifo)))
return;
while (kfifo_out(&priv->fifo, &ch, 1))
@ -270,13 +271,23 @@ static void kgdb_nmi_tty_cleanup(struct tty_struct *tty)
static int kgdb_nmi_tty_open(struct tty_struct *tty, struct file *file)
{
struct kgdb_nmi_tty_priv *priv = tty->driver_data;
unsigned int mode = file->f_flags & O_ACCMODE;
int ret;
return tty_port_open(&priv->port, tty, file);
ret = tty_port_open(&priv->port, tty, file);
if (!ret && (mode == O_RDONLY || mode == O_RDWR))
atomic_inc(&kgdb_nmi_num_readers);
return ret;
}
static void kgdb_nmi_tty_close(struct tty_struct *tty, struct file *file)
{
struct kgdb_nmi_tty_priv *priv = tty->driver_data;
unsigned int mode = file->f_flags & O_ACCMODE;
if (mode == O_RDONLY || mode == O_RDWR)
atomic_dec(&kgdb_nmi_num_readers);
tty_port_close(&priv->port, tty, file);
}
@ -313,12 +324,6 @@ static const struct tty_operations kgdb_nmi_tty_ops = {
.write = kgdb_nmi_tty_write,
};
static int kgdb_nmi_enable_console(int argc, const char *argv[])
{
kgdb_nmi_tty_enabled = !(argc == 1 && !strcmp(argv[1], "off"));
return 0;
}
int kgdb_register_nmi_console(void)
{
int ret;
@ -348,19 +353,10 @@ int kgdb_register_nmi_console(void)
goto err_drv_reg;
}
ret = kdb_register("nmi_console", kgdb_nmi_enable_console, "[off]",
"switch to Linux NMI console", 0);
if (ret) {
pr_err("%s: can't register kdb command: %d\n", __func__, ret);
goto err_kdb_reg;
}
register_console(&kgdb_nmi_console);
arch_kgdb_ops.enable_nmi(1);
return 0;
err_kdb_reg:
tty_unregister_driver(kgdb_nmi_tty_driver);
err_drv_reg:
put_tty_driver(kgdb_nmi_tty_driver);
return ret;
@ -375,8 +371,6 @@ int kgdb_unregister_nmi_console(void)
return 0;
arch_kgdb_ops.enable_nmi(0);
kdb_unregister("nmi_console");
ret = unregister_console(&kgdb_nmi_console);
if (ret)
return ret;

View File

@ -154,11 +154,6 @@ lqasc_stop_rx(struct uart_port *port)
ltq_w32(ASCWHBSTATE_CLRREN, port->membase + LTQ_ASC_WHBSTATE);
}
static void
lqasc_enable_ms(struct uart_port *port)
{
}
static int
lqasc_rx_chars(struct uart_port *port)
{
@ -568,7 +563,6 @@ static struct uart_ops lqasc_pops = {
.stop_tx = lqasc_stop_tx,
.start_tx = lqasc_start_tx,
.stop_rx = lqasc_stop_rx,
.enable_ms = lqasc_enable_ms,
.break_ctl = lqasc_break_ctl,
.startup = lqasc_startup,
.shutdown = lqasc_shutdown,
@ -709,7 +703,7 @@ lqasc_probe(struct platform_device *pdev)
port = &ltq_port->port;
port->iotype = SERIAL_IO_MEM;
port->flags = ASYNC_BOOT_AUTOCONF | UPF_IOREMAP;
port->flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP;
port->ops = &lqasc_pops;
port->fifosize = 16;
port->type = PORT_LTQ_ASC,

View File

@ -427,12 +427,6 @@ static void serial_lpc32xx_stop_rx(struct uart_port *port)
LPC32XX_HSU_FE_INT), LPC32XX_HSUART_IIR(port->membase));
}
/* port->lock held by caller. */
static void serial_lpc32xx_enable_ms(struct uart_port *port)
{
/* Modem status is not supported */
}
/* port->lock is not held. */
static void serial_lpc32xx_break_ctl(struct uart_port *port,
int break_state)
@ -658,7 +652,6 @@ static struct uart_ops serial_lpc32xx_pops = {
.stop_tx = serial_lpc32xx_stop_tx,
.start_tx = serial_lpc32xx_start_tx,
.stop_rx = serial_lpc32xx_stop_rx,
.enable_ms = serial_lpc32xx_enable_ms,
.break_ctl = serial_lpc32xx_break_ctl,
.startup = serial_lpc32xx_startup,
.shutdown = serial_lpc32xx_shutdown,

View File

@ -1008,7 +1008,6 @@ static const struct uart_ops max310x_ops = {
.stop_tx = max310x_null_void,
.start_tx = max310x_start_tx,
.stop_rx = max310x_null_void,
.enable_ms = max310x_null_void,
.break_ctl = max310x_break_ctl,
.startup = max310x_startup,
.shutdown = max310x_shutdown,

View File

@ -150,12 +150,6 @@ static void mcf_break_ctl(struct uart_port *port, int break_state)
/****************************************************************************/
static void mcf_enable_ms(struct uart_port *port)
{
}
/****************************************************************************/
static int mcf_startup(struct uart_port *port)
{
struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
@ -507,7 +501,6 @@ static const struct uart_ops mcf_uart_ops = {
.start_tx = mcf_start_tx,
.stop_tx = mcf_stop_tx,
.stop_rx = mcf_stop_rx,
.enable_ms = mcf_enable_ms,
.break_ctl = mcf_break_ctl,
.startup = mcf_startup,
.shutdown = mcf_shutdown,
@ -544,7 +537,7 @@ int __init early_mcf_setup(struct mcf_platform_uart *platp)
port->iotype = SERIAL_IO_MEM;
port->irq = platp[i].irq;
port->uartclk = MCF_BUSCLK;
port->flags = ASYNC_BOOT_AUTOCONF;
port->flags = UPF_BOOT_AUTOCONF;
port->ops = &mcf_uart_ops;
}
@ -669,7 +662,7 @@ static int mcf_probe(struct platform_device *pdev)
port->irq = platp[i].irq;
port->uartclk = MCF_BUSCLK;
port->ops = &mcf_uart_ops;
port->flags = ASYNC_BOOT_AUTOCONF;
port->flags = UPF_BOOT_AUTOCONF;
uart_add_one_port(&mcf_driver, port);
}

View File

@ -308,9 +308,6 @@ static void men_z135_handle_tx(struct men_z135_port *uart)
if (port->x_char)
goto out;
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
/* calculate bytes to copy */
qlen = uart_circ_chars_pending(xmit);
if (qlen <= 0)
@ -357,6 +354,9 @@ static void men_z135_handle_tx(struct men_z135_port *uart)
port->icount.tx += n;
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
irq_en:
if (!uart_circ_empty(xmit))
men_z135_reg_set(uart, MEN_Z135_CONF_REG, MEN_Z135_IER_TXCIEN);

View File

@ -1336,10 +1336,6 @@ static void mpsc_stop_rx(struct uart_port *port)
mpsc_sdma_cmd(pi, SDMA_SDCM_AR);
}
static void mpsc_enable_ms(struct uart_port *port)
{
}
static void mpsc_break_ctl(struct uart_port *port, int ctl)
{
struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
@ -1674,7 +1670,6 @@ static struct uart_ops mpsc_pops = {
.stop_tx = mpsc_stop_tx,
.start_tx = mpsc_start_tx,
.stop_rx = mpsc_stop_rx,
.enable_ms = mpsc_enable_ms,
.break_ctl = mpsc_break_ctl,
.startup = mpsc_startup,
.shutdown = mpsc_shutdown,

View File

@ -698,10 +698,6 @@ static void serial_m3110_pm(struct uart_port *port, unsigned int state,
{
}
static void serial_m3110_enable_ms(struct uart_port *port)
{
}
static struct uart_ops serial_m3110_ops = {
.tx_empty = serial_m3110_tx_empty,
.set_mctrl = serial_m3110_set_mctrl,
@ -709,7 +705,6 @@ static struct uart_ops serial_m3110_ops = {
.stop_tx = serial_m3110_stop_tx,
.start_tx = serial_m3110_start_tx,
.stop_rx = serial_m3110_stop_rx,
.enable_ms = serial_m3110_enable_ms,
.break_ctl = serial_m3110_break_ctl,
.startup = serial_m3110_startup,
.shutdown = serial_m3110_shutdown,

View File

@ -125,14 +125,14 @@ static void handle_rx_dm(struct uart_port *port, unsigned int misr)
port->icount.rx += count;
while (count > 0) {
unsigned int c;
unsigned char buf[4];
sr = msm_read(port, UART_SR);
if ((sr & UART_SR_RX_READY) == 0) {
msm_port->old_snap_state -= count;
break;
}
c = msm_read(port, UARTDM_RF);
ioread32_rep(port->membase + UARTDM_RF, buf, 1);
if (sr & UART_SR_RX_BREAK) {
port->icount.brk++;
if (uart_handle_break(port))
@ -141,8 +141,7 @@ static void handle_rx_dm(struct uart_port *port, unsigned int misr)
port->icount.frame++;
/* TODO: handle sysrq */
tty_insert_flip_string(tport, (char *)&c,
(count > 4) ? 4 : count);
tty_insert_flip_string(tport, buf, min(count, 4));
count -= 4;
}
@ -219,6 +218,12 @@ static void handle_tx(struct uart_port *port)
struct msm_port *msm_port = UART_TO_MSM(port);
unsigned int tx_count, num_chars;
unsigned int tf_pointer = 0;
void __iomem *tf;
if (msm_port->is_uartdm)
tf = port->membase + UARTDM_TF;
else
tf = port->membase + UART_TF;
tx_count = uart_circ_chars_pending(xmit);
tx_count = min3(tx_count, (unsigned int)UART_XMIT_SIZE - xmit->tail,
@ -228,8 +233,7 @@ static void handle_tx(struct uart_port *port)
if (msm_port->is_uartdm)
reset_dm_count(port, tx_count + 1);
msm_write(port, port->x_char,
msm_port->is_uartdm ? UARTDM_TF : UART_TF);
iowrite8_rep(tf, &port->x_char, 1);
port->icount.tx++;
port->x_char = 0;
} else if (tx_count && msm_port->is_uartdm) {
@ -239,7 +243,6 @@ static void handle_tx(struct uart_port *port)
while (tf_pointer < tx_count) {
int i;
char buf[4] = { 0 };
unsigned int *bf = (unsigned int *)&buf;
if (!(msm_read(port, UART_SR) & UART_SR_TX_READY))
break;
@ -255,7 +258,7 @@ static void handle_tx(struct uart_port *port)
port->icount.tx++;
}
msm_write(port, *bf, msm_port->is_uartdm ? UARTDM_TF : UART_TF);
iowrite32_rep(tf, buf, 1);
xmit->tail = (xmit->tail + num_chars) & (UART_XMIT_SIZE - 1);
tf_pointer += num_chars;
}
@ -861,12 +864,18 @@ static void msm_console_write(struct console *co, const char *s,
struct msm_port *msm_port;
int num_newlines = 0;
bool replaced = false;
void __iomem *tf;
BUG_ON(co->index < 0 || co->index >= UART_NR);
port = get_port_from_line(co->index);
msm_port = UART_TO_MSM(port);
if (msm_port->is_uartdm)
tf = port->membase + UARTDM_TF;
else
tf = port->membase + UART_TF;
/* Account for newlines that will get a carriage return added */
for (i = 0; i < count; i++)
if (s[i] == '\n')
@ -882,7 +891,6 @@ static void msm_console_write(struct console *co, const char *s,
int j;
unsigned int num_chars;
char buf[4] = { 0 };
unsigned int *bf = (unsigned int *)&buf;
if (msm_port->is_uartdm)
num_chars = min(count - i, (unsigned int)sizeof(buf));
@ -907,7 +915,7 @@ static void msm_console_write(struct console *co, const char *s,
while (!(msm_read(port, UART_SR) & UART_SR_TX_READY))
cpu_relax();
msm_write(port, *bf, msm_port->is_uartdm ? UARTDM_TF : UART_TF);
iowrite32_rep(tf, buf, 1);
i += num_chars;
}
spin_unlock(&port->lock);
@ -917,7 +925,7 @@ static int __init msm_console_setup(struct console *co, char *options)
{
struct uart_port *port;
struct msm_port *msm_port;
int baud, flow, bits, parity;
int baud = 0, flow, bits, parity;
if (unlikely(co->index >= UART_NR || co->index < 0))
return -ENXIO;
@ -1057,7 +1065,7 @@ static int msm_serial_remove(struct platform_device *pdev)
return 0;
}
static struct of_device_id msm_match_table[] = {
static const struct of_device_id msm_match_table[] = {
{ .compatible = "qcom,msm-uart" },
{ .compatible = "qcom,msm-uartdm" },
{}

View File

@ -126,13 +126,13 @@
static inline
void msm_write(struct uart_port *port, unsigned int val, unsigned int off)
{
__raw_writel(val, port->membase + off);
writel_relaxed(val, port->membase + off);
}
static inline
unsigned int msm_read(struct uart_port *port, unsigned int off)
{
return __raw_readl(port->membase + off);
return readl_relaxed(port->membase + off);
}
/*

View File

@ -168,16 +168,6 @@ static void mux_stop_rx(struct uart_port *port)
{
}
/**
* mux_enable_ms - Enable modum status interrupts.
* @port: Ptr to the uart_port.
*
* The Serial Mux does not support this function.
*/
static void mux_enable_ms(struct uart_port *port)
{
}
/**
* mux_break_ctl - Control the transmitssion of a break signal.
* @port: Ptr to the uart_port.
@ -449,7 +439,6 @@ static struct uart_ops mux_pops = {
.stop_tx = mux_stop_tx,
.start_tx = mux_start_tx,
.stop_rx = mux_stop_rx,
.enable_ms = mux_enable_ms,
.break_ctl = mux_break_ctl,
.startup = mux_startup,
.shutdown = mux_shutdown,

View File

@ -815,17 +815,11 @@ static void mxs_auart_break_ctl(struct uart_port *u, int ctl)
u->membase + AUART_LINECTRL_CLR);
}
static void mxs_auart_enable_ms(struct uart_port *port)
{
/* just empty */
}
static struct uart_ops mxs_auart_ops = {
.tx_empty = mxs_auart_tx_empty,
.start_tx = mxs_auart_start_tx,
.stop_tx = mxs_auart_stop_tx,
.stop_rx = mxs_auart_stop_rx,
.enable_ms = mxs_auart_enable_ms,
.break_ctl = mxs_auart_break_ctl,
.set_mctrl = mxs_auart_set_mctrl,
.get_mctrl = mxs_auart_get_mctrl,

View File

@ -240,11 +240,6 @@ static void nwpserial_break_ctl(struct uart_port *port, int ctl)
/* N/A */
}
static void nwpserial_enable_ms(struct uart_port *port)
{
/* N/A */
}
static void nwpserial_stop_rx(struct uart_port *port)
{
struct nwpserial_port *up;
@ -315,7 +310,6 @@ static struct uart_ops nwpserial_pops = {
.stop_tx = nwpserial_stop_tx,
.start_tx = nwpserial_start_tx,
.stop_rx = nwpserial_stop_rx,
.enable_ms = nwpserial_enable_ms,
.break_ctl = nwpserial_break_ctl,
.startup = nwpserial_startup,
.shutdown = nwpserial_shutdown,

View File

@ -736,9 +736,10 @@ static void pch_request_dma(struct uart_port *port)
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
dma_dev = pci_get_bus_and_slot(priv->pdev->bus->number,
PCI_DEVFN(0xa, 0)); /* Get DMA's dev
information */
/* Get DMA's dev information */
dma_dev = pci_get_slot(priv->pdev->bus,
PCI_DEVFN(PCI_SLOT(priv->pdev->devfn), 0));
/* Set Tx DMA */
param = &priv->param_tx;
param->dma_dev = &dma_dev->dev;
@ -1047,7 +1048,7 @@ static unsigned int dma_handle_tx(struct eg20t_port *priv)
priv->sg_tx_p, nent, DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc) {
dev_err(priv->port.dev, "%s:device_prep_slave_sg Failed\n",
dev_err(priv->port.dev, "%s:dmaengine_prep_slave_sg Failed\n",
__func__);
return 0;
}

View File

@ -778,7 +778,7 @@ static struct uart_ops serial_pxa_pops = {
.request_port = serial_pxa_request_port,
.config_port = serial_pxa_config_port,
.verify_port = serial_pxa_verify_port,
#ifdef CONFIG_CONSOLE_POLL
#if defined(CONFIG_CONSOLE_POLL) && defined(CONFIG_SERIAL_PXA_CONSOLE)
.poll_get_char = serial_pxa_get_poll_char,
.poll_put_char = serial_pxa_put_poll_char,
#endif

View File

@ -203,10 +203,6 @@ static void s3c24xx_serial_stop_rx(struct uart_port *port)
}
}
static void s3c24xx_serial_enable_ms(struct uart_port *port)
{
}
static inline struct s3c24xx_uart_info *s3c24xx_port_to_info(struct uart_port *port)
{
return to_ourport(port)->info;
@ -952,7 +948,6 @@ static struct uart_ops s3c24xx_serial_ops = {
.stop_tx = s3c24xx_serial_stop_tx,
.start_tx = s3c24xx_serial_start_tx,
.stop_rx = s3c24xx_serial_stop_rx,
.enable_ms = s3c24xx_serial_enable_ms,
.break_ctl = s3c24xx_serial_break_ctl,
.startup = s3c24xx_serial_startup,
.shutdown = s3c24xx_serial_shutdown,
@ -1226,8 +1221,8 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
wr_regl(port, S3C64XX_UINTSP, 0xf);
}
dbg("port: map=%08x, mem=%p, irq=%d (%d,%d), clock=%u\n",
port->mapbase, port->membase, port->irq,
dbg("port: map=%pa, mem=%p, irq=%d (%d,%d), clock=%u\n",
&port->mapbase, port->membase, port->irq,
ourport->rx_irq, ourport->tx_irq, port->uartclk);
/* reset the fifos (and setup the uart) */
@ -1274,12 +1269,20 @@ static inline struct s3c24xx_serial_drv_data *s3c24xx_get_driver_data(
static int s3c24xx_serial_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct s3c24xx_uart_port *ourport;
int index = probe_index;
int ret;
dbg("s3c24xx_serial_probe(%p) %d\n", pdev, probe_index);
if (np) {
ret = of_alias_get_id(np, "serial");
if (ret >= 0)
index = ret;
}
ourport = &s3c24xx_serial_ports[probe_index];
dbg("s3c24xx_serial_probe(%p) %d\n", pdev, index);
ourport = &s3c24xx_serial_ports[index];
ourport->drv_data = s3c24xx_get_driver_data(pdev);
if (!ourport->drv_data) {
@ -1293,9 +1296,15 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
dev_get_platdata(&pdev->dev) :
ourport->drv_data->def_cfg;
ourport->port.fifosize = (ourport->info->fifosize) ?
ourport->info->fifosize :
ourport->drv_data->fifosize[probe_index];
if (np)
of_property_read_u32(np,
"samsung,uart-fifosize", &ourport->port.fifosize);
if (!ourport->port.fifosize) {
ourport->port.fifosize = (ourport->info->fifosize) ?
ourport->info->fifosize :
ourport->drv_data->fifosize[index];
}
probe_index++;
@ -1303,7 +1312,7 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
ret = s3c24xx_serial_init_port(ourport, pdev);
if (ret < 0)
goto probe_err;
return ret;
if (!s3c24xx_uart_drv.state) {
ret = uart_register_driver(&s3c24xx_uart_drv);
@ -1335,9 +1344,6 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "failed to add cpufreq notifier\n");
return 0;
probe_err:
return ret;
}
static int s3c24xx_serial_remove(struct platform_device *dev)
@ -1537,8 +1543,8 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud,
case S3C2410_LCON_CS7:
*bits = 7;
break;
default:
case S3C2410_LCON_CS8:
default:
*bits = 8;
break;
}
@ -1712,9 +1718,7 @@ static struct s3c24xx_serial_drv_data s3c2440_serial_drv_data = {
#define S3C2440_SERIAL_DRV_DATA (kernel_ulong_t)NULL
#endif
#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410) || \
defined(CONFIG_CPU_S5P6440) || defined(CONFIG_CPU_S5P6450) || \
defined(CONFIG_CPU_S5PC100)
#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
static struct s3c24xx_serial_drv_data s3c6400_serial_drv_data = {
.info = &(struct s3c24xx_uart_info) {
.name = "Samsung S3C6400 UART",

View File

@ -991,7 +991,6 @@ static const struct uart_ops sc16is7xx_ops = {
.stop_tx = sc16is7xx_stop_tx,
.start_tx = sc16is7xx_start_tx,
.stop_rx = sc16is7xx_stop_rx,
.enable_ms = sc16is7xx_null_void,
.break_ctl = sc16is7xx_break_ctl,
.startup = sc16is7xx_startup,
.shutdown = sc16is7xx_shutdown,
@ -1061,7 +1060,6 @@ static int sc16is7xx_probe(struct device *dev,
struct regmap *regmap, int irq, unsigned long flags)
{
unsigned long freq, *pfreq = dev_get_platdata(dev);
struct clk *clk;
int i, ret;
struct sc16is7xx_port *s;
@ -1077,14 +1075,14 @@ static int sc16is7xx_probe(struct device *dev,
return -ENOMEM;
}
clk = devm_clk_get(dev, NULL);
if (IS_ERR(clk)) {
s->clk = devm_clk_get(dev, NULL);
if (IS_ERR(s->clk)) {
if (pfreq)
freq = *pfreq;
else
return PTR_ERR(clk);
return PTR_ERR(s->clk);
} else {
freq = clk_get_rate(clk);
freq = clk_get_rate(s->clk);
}
s->regmap = regmap;

View File

@ -533,11 +533,6 @@ static unsigned int sccnxp_tx_empty(struct uart_port *port)
return (val & SR_TXEMT) ? TIOCSER_TEMT : 0;
}
static void sccnxp_enable_ms(struct uart_port *port)
{
/* Do nothing */
}
static void sccnxp_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
struct sccnxp_port *s = dev_get_drvdata(port->dev);
@ -790,7 +785,6 @@ static const struct uart_ops sccnxp_ops = {
.stop_tx = sccnxp_stop_tx,
.start_tx = sccnxp_start_tx,
.stop_rx = sccnxp_stop_rx,
.enable_ms = sccnxp_enable_ms,
.break_ctl = sccnxp_break_ctl,
.startup = sccnxp_startup,
.shutdown = sccnxp_shutdown,

View File

@ -482,6 +482,9 @@ static void tegra_uart_stop_tx(struct uart_port *u)
struct dma_tx_state state;
int count;
if (tup->tx_in_progress != TEGRA_UART_TX_DMA)
return;
dmaengine_terminate_all(tup->tx_dma_chan);
dmaengine_tx_status(tup->tx_dma_chan, tup->tx_cookie, &state);
count = tup->tx_bytes_requested - state.residue;
@ -599,6 +602,7 @@ static void tegra_uart_handle_rx_dma(struct tegra_uart_port *tup,
dmaengine_terminate_all(tup->rx_dma_chan);
dmaengine_tx_status(tup->rx_dma_chan, tup->rx_cookie, &state);
async_tx_ack(tup->rx_dma_desc);
count = tup->rx_bytes_requested - state.residue;
/* If we are here, DMA is stopped */

View File

@ -243,6 +243,9 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state)
/*
* Turn off DTR and RTS early.
*/
if (uart_console(uport) && tty)
uport->cons->cflag = tty->termios.c_cflag;
if (!tty || (tty->termios.c_cflag & HUPCL))
uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS);
@ -447,6 +450,7 @@ static void uart_change_speed(struct tty_struct *tty, struct uart_state *state,
return;
termios = &tty->termios;
uport->ops->set_termios(uport, termios, old_termios);
/*
* Set flags based on termios cflag
@ -460,8 +464,6 @@ static void uart_change_speed(struct tty_struct *tty, struct uart_state *state,
clear_bit(ASYNCB_CHECK_CD, &port->flags);
else
set_bit(ASYNCB_CHECK_CD, &port->flags);
uport->ops->set_termios(uport, termios, old_termios);
}
static inline int __uart_put_char(struct uart_port *port,
@ -1050,6 +1052,15 @@ static int uart_do_autoconfig(struct tty_struct *tty,struct uart_state *state)
return ret;
}
static void uart_enable_ms(struct uart_port *uport)
{
/*
* Force modem status interrupts on
*/
if (uport->ops->enable_ms)
uport->ops->enable_ms(uport);
}
/*
* Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
* - mask passed in arg for lines of interest
@ -1073,11 +1084,7 @@ uart_wait_modem_status(struct uart_state *state, unsigned long arg)
*/
spin_lock_irq(&uport->lock);
memcpy(&cprev, &uport->icount, sizeof(struct uart_icount));
/*
* Force modem status interrupts on
*/
uport->ops->enable_ms(uport);
uart_enable_ms(uport);
spin_unlock_irq(&uport->lock);
add_wait_queue(&port->delta_msr_wait, &wait);
@ -1274,6 +1281,8 @@ static void uart_set_termios(struct tty_struct *tty,
}
uart_change_speed(tty, state, old_termios);
/* reload cflag from termios; port driver may have overriden flags */
cflag = tty->termios.c_cflag;
/* Handle transition to B0 status */
if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD))
@ -1360,8 +1369,8 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
tty_ldisc_flush(tty);
tty_port_tty_set(port, NULL);
spin_lock_irqsave(&port->lock, flags);
tty->closing = 0;
spin_lock_irqsave(&port->lock, flags);
if (port->blocked_open) {
spin_unlock_irqrestore(&port->lock, flags);
@ -1508,7 +1517,7 @@ static int uart_carrier_raised(struct tty_port *port)
struct uart_port *uport = state->uart_port;
int mctrl;
spin_lock_irq(&uport->lock);
uport->ops->enable_ms(uport);
uart_enable_ms(uport);
mctrl = uport->ops->get_mctrl(uport);
spin_unlock_irq(&uport->lock);
if (mctrl & TIOCM_CAR)
@ -1575,14 +1584,6 @@ static int uart_open(struct tty_struct *tty, struct file *filp)
(state->uart_port->flags & UPF_LOW_LATENCY) ? 1 : 0;
tty_port_tty_set(port, tty);
/*
* If the port is in the middle of closing, bail out now.
*/
if (tty_hung_up_p(filp)) {
retval = -EAGAIN;
goto err_dec_count;
}
/*
* Start up the serial port.
*/
@ -2563,12 +2564,6 @@ static const struct attribute_group tty_dev_attr_group = {
.attrs = tty_dev_attrs,
};
static const struct attribute_group *tty_dev_attr_groups[] = {
&tty_dev_attr_group,
NULL
};
/**
* uart_add_one_port - attach a driver-defined port structure
* @drv: pointer to the uart low level driver structure for this port
@ -2585,6 +2580,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
struct tty_port *port;
int ret = 0;
struct device *tty_dev;
int num_groups;
BUG_ON(in_interrupt());
@ -2618,12 +2614,26 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
uart_configure_port(drv, state, uport);
num_groups = 2;
if (uport->attr_group)
num_groups++;
uport->tty_groups = kcalloc(num_groups, sizeof(*uport->tty_groups),
GFP_KERNEL);
if (!uport->tty_groups) {
ret = -ENOMEM;
goto out;
}
uport->tty_groups[0] = &tty_dev_attr_group;
if (uport->attr_group)
uport->tty_groups[1] = uport->attr_group;
/*
* Register the port whether it's detected or not. This allows
* setserial to be used to alter this port's parameters.
*/
tty_dev = tty_port_register_device_attr(port, drv->tty_driver,
uport->line, uport->dev, port, tty_dev_attr_groups);
uport->line, uport->dev, port, uport->tty_groups);
if (likely(!IS_ERR(tty_dev))) {
device_set_wakeup_capable(tty_dev, 1);
} else {
@ -2702,6 +2712,7 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport)
*/
if (uport->type != PORT_UNKNOWN)
uport->ops->release_port(uport);
kfree(uport->tty_groups);
/*
* Indicate that there isn't a port here anymore.

View File

@ -142,7 +142,6 @@ struct uart_txx9_port {
#define TXX9_SIFCR_RDIL_12 0x00000180
#define TXX9_SIFCR_RDIL_MAX 0x00000180
#define TXX9_SIFCR_TDIL_MASK 0x00000018
#define TXX9_SIFCR_TDIL_MASK 0x00000018
#define TXX9_SIFCR_TDIL_1 0x00000000
#define TXX9_SIFCR_TDIL_4 0x00000001
#define TXX9_SIFCR_TDIL_8 0x00000010
@ -244,11 +243,6 @@ static void serial_txx9_stop_rx(struct uart_port *port)
up->port.read_status_mask &= ~TXX9_SIDISR_RDIS;
}
static void serial_txx9_enable_ms(struct uart_port *port)
{
/* TXX9-SIO can not control DTR... */
}
static void serial_txx9_initialize(struct uart_port *port)
{
struct uart_txx9_port *up = to_uart_txx9_port(port);
@ -858,7 +852,6 @@ static struct uart_ops serial_txx9_pops = {
.stop_tx = serial_txx9_stop_tx,
.start_tx = serial_txx9_start_tx,
.stop_rx = serial_txx9_stop_rx,
.enable_ms = serial_txx9_enable_ms,
.break_ctl = serial_txx9_break_ctl,
.startup = serial_txx9_startup,
.shutdown = serial_txx9_shutdown,

View File

@ -1560,13 +1560,6 @@ static void sci_stop_rx(struct uart_port *port)
serial_port_out(port, SCSCR, ctrl);
}
static void sci_enable_ms(struct uart_port *port)
{
/*
* Not supported by hardware, always a nop.
*/
}
static void sci_break_ctl(struct uart_port *port, int break_state)
{
struct sci_port *s = to_sci_port(port);
@ -1783,30 +1776,71 @@ static unsigned int sci_scbrr_calc(struct sci_port *s, unsigned int bps,
return ((freq + 16 * bps) / (32 * bps) - 1);
}
/* calculate frame length from SMR */
static int sci_baud_calc_frame_len(unsigned int smr_val)
{
int len = 10;
if (smr_val & SCSMR_CHR)
len--;
if (smr_val & SCSMR_PE)
len++;
if (smr_val & SCSMR_STOP)
len++;
return len;
}
/* calculate sample rate, BRR, and clock select for HSCIF */
static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq,
int *brr, unsigned int *srr,
unsigned int *cks)
unsigned int *cks, int frame_len)
{
int sr, c, br, err;
int sr, c, br, err, recv_margin;
int min_err = 1000; /* 100% */
int recv_max_margin = 0;
/* Find the combination of sample rate and clock select with the
smallest deviation from the desired baud rate. */
for (sr = 8; sr <= 32; sr++) {
for (c = 0; c <= 3; c++) {
/* integerized formulas from HSCIF documentation */
br = freq / (sr * (1 << (2 * c + 1)) * bps) - 1;
if (br < 0 || br > 255)
br = DIV_ROUND_CLOSEST(freq, (sr *
(1 << (2 * c + 1)) * bps)) - 1;
br = clamp(br, 0, 255);
err = DIV_ROUND_CLOSEST(freq, ((br + 1) * bps * sr *
(1 << (2 * c + 1)) / 1000)) -
1000;
if (err < 0)
continue;
err = freq / ((br + 1) * bps * sr *
(1 << (2 * c + 1)) / 1000) - 1000;
/* Calc recv margin
* M: Receive margin (%)
* N: Ratio of bit rate to clock (N = sampling rate)
* D: Clock duty (D = 0 to 1.0)
* L: Frame length (L = 9 to 12)
* F: Absolute value of clock frequency deviation
*
* M = |(0.5 - 1 / 2 * N) - ((L - 0.5) * F) -
* (|D - 0.5| / N * (1 + F))|
* NOTE: Usually, treat D for 0.5, F is 0 by this
* calculation.
*/
recv_margin = abs((500 -
DIV_ROUND_CLOSEST(1000, sr << 1)) / 10);
if (min_err > err) {
min_err = err;
*brr = br;
*srr = sr - 1;
*cks = c;
}
recv_max_margin = recv_margin;
} else if ((min_err == err) &&
(recv_margin > recv_max_margin))
recv_max_margin = recv_margin;
else
continue;
*brr = br;
*srr = sr - 1;
*cks = c;
}
}
@ -1840,10 +1874,19 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
{
struct sci_port *s = to_sci_port(port);
struct plat_sci_reg *reg;
unsigned int baud, smr_val, max_baud, cks = 0;
unsigned int baud, smr_val = 0, max_baud, cks = 0;
int t = -1;
unsigned int srr = 15;
if ((termios->c_cflag & CSIZE) == CS7)
smr_val |= SCSMR_CHR;
if (termios->c_cflag & PARENB)
smr_val |= SCSMR_PE;
if (termios->c_cflag & PARODD)
smr_val |= SCSMR_PE | SCSMR_ODD;
if (termios->c_cflag & CSTOPB)
smr_val |= SCSMR_STOP;
/*
* earlyprintk comes here early on with port->uartclk set to zero.
* the clock framework is not up and running at this point so here
@ -1857,8 +1900,9 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
baud = uart_get_baud_rate(port, termios, old, 0, max_baud);
if (likely(baud && port->uartclk)) {
if (s->cfg->type == PORT_HSCIF) {
int frame_len = sci_baud_calc_frame_len(smr_val);
sci_baud_calc_hscif(baud, port->uartclk, &t, &srr,
&cks);
&cks, frame_len);
} else {
t = sci_scbrr_calc(s, baud, port->uartclk);
for (cks = 0; t >= 256 && cks <= 3; cks++)
@ -1870,16 +1914,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
sci_reset(port);
smr_val = serial_port_in(port, SCSMR) & 3;
if ((termios->c_cflag & CSIZE) == CS7)
smr_val |= SCSMR_CHR;
if (termios->c_cflag & PARENB)
smr_val |= SCSMR_PE;
if (termios->c_cflag & PARODD)
smr_val |= SCSMR_PE | SCSMR_ODD;
if (termios->c_cflag & CSTOPB)
smr_val |= SCSMR_STOP;
smr_val |= serial_port_in(port, SCSMR) & 3;
uart_update_timeout(port, termios->c_cflag, baud);
@ -2080,7 +2115,6 @@ static struct uart_ops sci_uart_ops = {
.start_tx = sci_start_tx,
.stop_tx = sci_stop_tx,
.stop_rx = sci_stop_rx,
.enable_ms = sci_enable_ms,
.break_ctl = sci_break_ctl,
.startup = sci_startup,
.shutdown = sci_shutdown,

View File

@ -290,7 +290,8 @@ static void sirfsoc_uart_start_tx(struct uart_port *port)
if (sirfport->tx_dma_chan)
sirfsoc_uart_tx_with_dma(sirfport);
else {
sirfsoc_uart_pio_tx_chars(sirfport, 1);
sirfsoc_uart_pio_tx_chars(sirfport,
SIRFSOC_UART_IO_TX_REASONABLE_CNT);
wr_regl(port, ureg->sirfsoc_tx_fifo_op, SIRFUART_FIFO_START);
if (!sirfport->is_marco)
wr_regl(port, ureg->sirfsoc_int_en_reg,

View File

@ -449,4 +449,4 @@ struct sirfsoc_uart_port {
/* I/O Mode */
#define SIRFSOC_UART_IO_RX_MAX_CNT 256
#define SIRFSOC_UART_IO_TX_REASONABLE_CNT 6
#define SIRFSOC_UART_IO_TX_REASONABLE_CNT 256

View File

@ -274,15 +274,6 @@ static void snp_release_port(struct uart_port *port)
{
}
/**
* snp_enable_ms - Force modem status interrupts on - no-op for us
* @port: Port to operate on - we ignore - no-op function
*
*/
static void snp_enable_ms(struct uart_port *port)
{
}
/**
* snp_shutdown - shut down the port - free irq and disable - no-op for us
* @port: Port to shut down - we ignore
@ -396,7 +387,6 @@ static struct uart_ops sn_console_ops = {
.stop_tx = snp_stop_tx,
.start_tx = snp_start_tx,
.stop_rx = snp_stop_rx,
.enable_ms = snp_enable_ms,
.break_ctl = snp_break_ctl,
.startup = snp_startup,
.shutdown = snp_shutdown,

View File

@ -411,12 +411,6 @@ static void asc_stop_rx(struct uart_port *port)
asc_disable_rx_interrupts(port);
}
/* Force modem status interrupts on */
static void asc_enable_ms(struct uart_port *port)
{
/* Nothing here yet .. */
}
/* Handle breaks - ignored by us */
static void asc_break_ctl(struct uart_port *port, int break_state)
{
@ -533,12 +527,12 @@ static void asc_set_termios(struct uart_port *port, struct ktermios *termios,
* ASCBaudRate = ------------------------
* inputclock
*
* However to keep the maths inside 32bits we divide top and
* bottom by 64. The +1 is to avoid a divide by zero if the
* input clock rate is something unexpected.
* To keep maths inside 64bits, we divide inputclock by 16.
*/
u32 counter = (baud * 16384) / ((port->uartclk / 64) + 1);
asc_out(port, ASC_BAUDRATE, counter);
u64 dividend = (u64)baud * (1 << 16);
do_div(dividend, port->uartclk / 16);
asc_out(port, ASC_BAUDRATE, dividend);
ctrl_val |= ASC_CTL_BAUDMODE;
}
@ -644,7 +638,6 @@ static struct uart_ops asc_uart_ops = {
.start_tx = asc_start_tx,
.stop_tx = asc_stop_tx,
.stop_rx = asc_stop_rx,
.enable_ms = asc_enable_ms,
.break_ctl = asc_break_ctl,
.startup = asc_startup,
.shutdown = asc_shutdown,
@ -849,7 +842,8 @@ static int asc_console_setup(struct console *co, char *options)
* this to be called during the uart port registration when the
* driver gets probed and the port should be mapped at that point.
*/
BUG_ON(ascport->port.mapbase == 0 || ascport->port.membase == NULL);
if (ascport->port.mapbase == 0 || ascport->port.membase == NULL)
return -ENXIO;
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);

View File

@ -285,11 +285,6 @@ static void sunhv_stop_rx(struct uart_port *port)
{
}
/* port->lock held by caller. */
static void sunhv_enable_ms(struct uart_port *port)
{
}
/* port->lock is not held. */
static void sunhv_break_ctl(struct uart_port *port, int break_state)
{
@ -379,7 +374,6 @@ static struct uart_ops sunhv_pops = {
.start_tx = sunhv_start_tx,
.send_xchar = sunhv_send_xchar,
.stop_rx = sunhv_stop_rx,
.enable_ms = sunhv_enable_ms,
.break_ctl = sunhv_break_ctl,
.startup = sunhv_startup,
.shutdown = sunhv_shutdown,

View File

@ -476,12 +476,6 @@ static void sunsab_stop_rx(struct uart_port *port)
writeb(up->interrupt_mask1, &up->regs->w.imr0);
}
/* port->lock held by caller. */
static void sunsab_enable_ms(struct uart_port *port)
{
/* For now we always receive these interrupts. */
}
/* port->lock is not held. */
static void sunsab_break_ctl(struct uart_port *port, int break_state)
{
@ -810,7 +804,6 @@ static struct uart_ops sunsab_pops = {
.start_tx = sunsab_start_tx,
.send_xchar = sunsab_send_xchar,
.stop_rx = sunsab_stop_rx,
.enable_ms = sunsab_enable_ms,
.break_ctl = sunsab_break_ctl,
.startup = sunsab_startup,
.shutdown = sunsab_shutdown,

View File

@ -314,15 +314,6 @@ static void tilegx_stop_rx(struct uart_port *port)
mutex_unlock(&tile_uart->mutex);
}
/*
* Enable modem status interrupts.
*/
static void tilegx_enable_ms(struct uart_port *port)
{
/* N/A */
}
/*
* Control the transmission of a break signal.
*/
@ -614,7 +605,6 @@ static const struct uart_ops tilegx_ops = {
.stop_tx = tilegx_stop_tx,
.start_tx = tilegx_start_tx,
.stop_rx = tilegx_stop_rx,
.enable_ms = tilegx_enable_ms,
.break_ctl = tilegx_break_ctl,
.startup = tilegx_startup,
.shutdown = tilegx_shutdown,

View File

@ -244,11 +244,6 @@ static void timbuart_mctrl_check(struct uart_port *port, u32 isr, u32 *ier)
*ier |= CTS_DELTA;
}
static void timbuart_enable_ms(struct uart_port *port)
{
/* N/A */
}
static void timbuart_break_ctl(struct uart_port *port, int ctl)
{
/* N/A */
@ -405,7 +400,6 @@ static struct uart_ops timbuart_ops = {
.start_tx = timbuart_start_tx,
.flush_buffer = timbuart_flush_buffer,
.stop_rx = timbuart_stop_rx,
.enable_ms = timbuart_enable_ms,
.break_ctl = timbuart_break_ctl,
.startup = timbuart_startup,
.shutdown = timbuart_shutdown,

View File

@ -250,11 +250,6 @@ static void ulite_stop_rx(struct uart_port *port)
| ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN;
}
static void ulite_enable_ms(struct uart_port *port)
{
/* N/A */
}
static void ulite_break_ctl(struct uart_port *port, int ctl)
{
/* N/A */
@ -395,7 +390,6 @@ static struct uart_ops ulite_ops = {
.stop_tx = ulite_stop_tx,
.start_tx = ulite_start_tx,
.stop_rx = ulite_stop_rx,
.enable_ms = ulite_enable_ms,
.break_ctl = ulite_break_ctl,
.startup = ulite_startup,
.shutdown = ulite_shutdown,

View File

@ -435,16 +435,6 @@ static void qe_uart_stop_rx(struct uart_port *port)
clrbits16(&qe_port->uccp->uccm, UCC_UART_UCCE_RX);
}
/*
* Enable status change interrupts
*
* We don't support status change interrupts, but we need to define this
* function otherwise the kernel will panic.
*/
static void qe_uart_enable_ms(struct uart_port *port)
{
}
/* Start or stop sending break signal
*
* This function controls the sending of a break signal. If break_state=1,
@ -1102,7 +1092,6 @@ static struct uart_ops qe_uart_pops = {
.stop_tx = qe_uart_stop_tx,
.start_tx = qe_uart_start_tx,
.stop_rx = qe_uart_stop_rx,
.enable_ms = qe_uart_enable_ms,
.break_ctl = qe_uart_break_ctl,
.startup = qe_uart_startup,
.shutdown = qe_uart_shutdown,

View File

@ -918,11 +918,6 @@ static void cdns_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
/* N/A */
}
static void cdns_uart_enable_ms(struct uart_port *port)
{
/* N/A */
}
#ifdef CONFIG_CONSOLE_POLL
static int cdns_uart_poll_get_char(struct uart_port *port)
{
@ -974,7 +969,6 @@ static void cdns_uart_poll_put_char(struct uart_port *port, unsigned char c)
static struct uart_ops cdns_uart_ops = {
.set_mctrl = cdns_uart_set_mctrl,
.get_mctrl = cdns_uart_get_mctrl,
.enable_ms = cdns_uart_enable_ms,
.start_tx = cdns_uart_start_tx,
.stop_tx = cdns_uart_stop_tx,
.stop_rx = cdns_uart_stop_rx,

View File

@ -3267,7 +3267,6 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
DECLARE_WAITQUEUE(wait, current);
int retval;
bool do_clocal = false;
bool extra_count = false;
unsigned long flags;
int dcd;
struct tty_port *port = &info->port;
@ -3300,10 +3299,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
__FILE__,__LINE__, tty->driver->name, port->count );
spin_lock_irqsave(&info->irq_spinlock, flags);
if (!tty_hung_up_p(filp)) {
extra_count = true;
port->count--;
}
port->count--;
spin_unlock_irqrestore(&info->irq_spinlock, flags);
port->blocked_open++;
@ -3342,7 +3338,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
remove_wait_queue(&port->open_wait, &wait);
/* FIXME: Racy on hangup during close wait */
if (extra_count)
if (!tty_hung_up_p(filp))
port->count++;
port->blocked_open--;
@ -3403,7 +3399,7 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp)
__FILE__,__LINE__,tty->driver->name, info->port.count);
/* If port is closing, signal caller to try again */
if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){
if (info->port.flags & ASYNC_CLOSING){
wait_event_interruptible_tty(tty, info->port.close_wait,
!(info->port.flags & ASYNC_CLOSING));
retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?

View File

@ -673,7 +673,7 @@ static int open(struct tty_struct *tty, struct file *filp)
DBGINFO(("%s open, old ref count = %d\n", info->device_name, info->port.count));
/* If port is closing, signal caller to try again */
if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){
if (info->port.flags & ASYNC_CLOSING){
wait_event_interruptible_tty(tty, info->port.close_wait,
!(info->port.flags & ASYNC_CLOSING));
retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
@ -3273,7 +3273,6 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
DECLARE_WAITQUEUE(wait, current);
int retval;
bool do_clocal = false;
bool extra_count = false;
unsigned long flags;
int cd;
struct tty_port *port = &info->port;
@ -3300,10 +3299,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
add_wait_queue(&port->open_wait, &wait);
spin_lock_irqsave(&info->lock, flags);
if (!tty_hung_up_p(filp)) {
extra_count = true;
port->count--;
}
port->count--;
spin_unlock_irqrestore(&info->lock, flags);
port->blocked_open++;
@ -3338,7 +3334,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
set_current_state(TASK_RUNNING);
remove_wait_queue(&port->open_wait, &wait);
if (extra_count)
if (!tty_hung_up_p(filp))
port->count++;
port->blocked_open--;

View File

@ -753,7 +753,7 @@ static int open(struct tty_struct *tty, struct file *filp)
__FILE__,__LINE__,tty->driver->name, info->port.count);
/* If port is closing, signal caller to try again */
if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){
if (info->port.flags & ASYNC_CLOSING){
wait_event_interruptible_tty(tty, info->port.close_wait,
!(info->port.flags & ASYNC_CLOSING));
retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
@ -3288,7 +3288,6 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
DECLARE_WAITQUEUE(wait, current);
int retval;
bool do_clocal = false;
bool extra_count = false;
unsigned long flags;
int cd;
struct tty_port *port = &info->port;
@ -3322,10 +3321,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
__FILE__,__LINE__, tty->driver->name, port->count );
spin_lock_irqsave(&info->lock, flags);
if (!tty_hung_up_p(filp)) {
extra_count = true;
port->count--;
}
port->count--;
spin_unlock_irqrestore(&info->lock, flags);
port->blocked_open++;
@ -3362,8 +3358,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
set_current_state(TASK_RUNNING);
remove_wait_queue(&port->open_wait, &wait);
if (extra_count)
if (!tty_hung_up_p(filp))
port->count++;
port->blocked_open--;

View File

@ -156,20 +156,6 @@ static void release_tty(struct tty_struct *tty, int idx);
static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
static void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
/**
* alloc_tty_struct - allocate a tty object
*
* Return a new empty tty structure. The data fields have not
* been initialized in any way but has been zeroed
*
* Locking: none
*/
struct tty_struct *alloc_tty_struct(void)
{
return kzalloc(sizeof(struct tty_struct), GFP_KERNEL);
}
/**
* free_tty_struct - free a disused tty
* @tty: tty struct to free
@ -688,7 +674,7 @@ static void __tty_hangup(struct tty_struct *tty, int exit_session)
for (n = 0; n < closecount; n++)
tty->ops->close(tty, cons_filp);
} else if (tty->ops->hangup)
(tty->ops->hangup)(tty);
tty->ops->hangup(tty);
/*
* We don't want to have driver/ldisc interactions beyond
* the ones we did here. The driver layer expects no
@ -1455,12 +1441,11 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)
if (!try_module_get(driver->owner))
return ERR_PTR(-ENODEV);
tty = alloc_tty_struct();
tty = alloc_tty_struct(driver, idx);
if (!tty) {
retval = -ENOMEM;
goto err_module_put;
}
initialize_tty_struct(tty, driver, idx);
tty_lock(tty);
retval = tty_driver_install_tty(driver, tty);
@ -3003,19 +2988,21 @@ static struct device *tty_get_device(struct tty_struct *tty)
/**
* initialize_tty_struct
* @tty: tty to initialize
* alloc_tty_struct
*
* This subroutine initializes a tty structure that has been newly
* allocated.
* This subroutine allocates and initializes a tty structure.
*
* Locking: none - tty in question must not be exposed at this point
* Locking: none - tty in question is not exposed at this point
*/
void initialize_tty_struct(struct tty_struct *tty,
struct tty_driver *driver, int idx)
struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx)
{
memset(tty, 0, sizeof(struct tty_struct));
struct tty_struct *tty;
tty = kzalloc(sizeof(*tty), GFP_KERNEL);
if (!tty)
return NULL;
kref_init(&tty->kref);
tty->magic = TTY_MAGIC;
tty_ldisc_init(tty);
@ -3039,6 +3026,8 @@ void initialize_tty_struct(struct tty_struct *tty,
tty->index = idx;
tty_line_name(driver, idx, tty->name);
tty->dev = tty_get_device(tty);
return tty;
}
/**

View File

@ -227,6 +227,8 @@ out:
*
* Perform port level tty hangup flag and count changes. Drop the tty
* reference.
*
* Caller holds tty lock.
*/
void tty_port_hangup(struct tty_port *port)
@ -348,6 +350,11 @@ EXPORT_SYMBOL(tty_port_lower_dtr_rts);
* do carrier detect and the dtr_rts method if it supports software
* management of these lines. Note that the dtr/rts raise is done each
* iteration as a hangup may have previously dropped them while we wait.
*
* Caller holds tty lock.
*
* NB: May drop and reacquire tty lock when blocking, so tty and tty_port
* may have changed state (eg., may have been hung up).
*/
int tty_port_block_til_ready(struct tty_port *port,
@ -358,7 +365,7 @@ int tty_port_block_til_ready(struct tty_port *port,
DEFINE_WAIT(wait);
/* block if port is in the process of being closed */
if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
if (port->flags & ASYNC_CLOSING) {
wait_event_interruptible_tty(tty, port->close_wait,
!(port->flags & ASYNC_CLOSING));
if (port->flags & ASYNC_HUP_NOTIFY)
@ -392,8 +399,7 @@ int tty_port_block_til_ready(struct tty_port *port,
/* The port lock protects the port counts */
spin_lock_irqsave(&port->lock, flags);
if (!tty_hung_up_p(filp))
port->count--;
port->count--;
port->blocked_open++;
spin_unlock_irqrestore(&port->lock, flags);
@ -458,6 +464,10 @@ static void tty_port_drain_delay(struct tty_port *port, struct tty_struct *tty)
schedule_timeout_interruptible(timeout);
}
/* Caller holds tty lock.
* NB: may drop and reacquire tty lock (in tty_wait_until_sent_from_close())
* so tty and tty port may have changed state (but not hung up or reopened).
*/
int tty_port_close_start(struct tty_port *port,
struct tty_struct *tty, struct file *filp)
{
@ -486,9 +496,10 @@ int tty_port_close_start(struct tty_port *port,
return 0;
}
set_bit(ASYNCB_CLOSING, &port->flags);
tty->closing = 1;
spin_unlock_irqrestore(&port->lock, flags);
tty->closing = 1;
if (test_bit(ASYNCB_INITIALIZED, &port->flags)) {
/* Don't block on a stalled port, just pull the chain */
if (tty->flow_stopped)
@ -506,13 +517,15 @@ int tty_port_close_start(struct tty_port *port,
}
EXPORT_SYMBOL(tty_port_close_start);
/* Caller holds tty lock */
void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
{
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
tty->closing = 0;
spin_lock_irqsave(&port->lock, flags);
if (port->blocked_open) {
spin_unlock_irqrestore(&port->lock, flags);
if (port->close_delay) {
@ -528,6 +541,15 @@ void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
}
EXPORT_SYMBOL(tty_port_close_end);
/**
* tty_port_close
*
* Caller holds tty lock
*
* NB: may drop and reacquire tty lock (in tty_port_close_start()->
* tty_wait_until_sent_from_close()) so tty and tty_port may have changed
* state (but not hung up or reopened).
*/
void tty_port_close(struct tty_port *port, struct tty_struct *tty,
struct file *filp)
{
@ -558,12 +580,19 @@ int tty_port_install(struct tty_port *port, struct tty_driver *driver,
}
EXPORT_SYMBOL_GPL(tty_port_install);
/**
* tty_port_open
*
* Caller holds tty lock.
*
* NB: may drop and reacquire tty lock (in tty_port_block_til_ready()) so
* tty and tty_port may have changed state (eg., may be hung up now)
*/
int tty_port_open(struct tty_port *port, struct tty_struct *tty,
struct file *filp)
{
spin_lock_irq(&port->lock);
if (!tty_hung_up_p(filp))
++port->count;
++port->count;
spin_unlock_irq(&port->lock);
tty_port_tty_set(port, tty);

View File

@ -74,8 +74,10 @@ struct uart_8250_port {
struct list_head list; /* ports on this IRQ */
unsigned short capabilities; /* port capabilities */
unsigned short bugs; /* port bugs */
bool fifo_bug; /* min RX trigger if enabled */
unsigned int tx_loadsz; /* transmit fifo load size */
unsigned char acr;
unsigned char fcr;
unsigned char ier;
unsigned char lcr;
unsigned char mcr;
@ -100,6 +102,11 @@ struct uart_8250_port {
void (*dl_write)(struct uart_8250_port *, int);
};
static inline struct uart_8250_port *up_to_u8250p(struct uart_port *up)
{
return container_of(up, struct uart_8250_port, port);
}
int serial8250_register_8250_port(struct uart_8250_port *);
void serial8250_unregister_port(int line);
void serial8250_suspend_port(int line);

View File

@ -199,6 +199,8 @@ struct uart_port {
unsigned char suspended;
unsigned char irq_wake;
unsigned char unused[2];
struct attribute_group *attr_group; /* port specific attributes */
const struct attribute_group **tty_groups; /* all attributes (serial core use only) */
void *private_data; /* generic platform data pointer */
};

View File

@ -477,13 +477,11 @@ extern int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg);
extern int tty_perform_flush(struct tty_struct *tty, unsigned long arg);
extern void tty_default_fops(struct file_operations *fops);
extern struct tty_struct *alloc_tty_struct(void);
extern struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx);
extern int tty_alloc_file(struct file *file);
extern void tty_add_file(struct tty_struct *tty, struct file *file);
extern void tty_free_file(struct file *file);
extern void free_tty_struct(struct tty_struct *tty);
extern void initialize_tty_struct(struct tty_struct *tty,
struct tty_driver *driver, int idx);
extern void deinitialize_tty_struct(struct tty_struct *tty);
extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx);
extern int tty_release(struct inode *inode, struct file *filp);

View File

@ -35,14 +35,14 @@
* This routine is mandatory; if this routine is not filled in,
* the attempted open will fail with ENODEV.
*
* Required method.
*
* Required method. Called with tty lock held.
*
* void (*close)(struct tty_struct * tty, struct file * filp);
*
* This routine is called when a particular tty device is closed.
* Note: called even if the corresponding open() failed.
*
* Required method.
* Required method. Called with tty lock held.
*
* void (*shutdown)(struct tty_struct * tty);
*
@ -172,6 +172,8 @@
*
* Optional:
*
* Called with tty lock held.
*
* int (*break_ctl)(struct tty_struct *tty, int state);
*
* This optional routine requests the tty driver to turn on or

View File

@ -88,6 +88,11 @@
#define UART_FCR6_T_TRIGGER_30 0x30 /* Mask for transmit trigger set at 30 */
#define UART_FCR7_64BYTE 0x20 /* Go into 64 byte mode (TI16C750) */
#define UART_FCR_R_TRIG_SHIFT 6
#define UART_FCR_R_TRIG_BITS(x) \
(((x) & UART_FCR_TRIGGER_MASK) >> UART_FCR_R_TRIG_SHIFT)
#define UART_FCR_R_TRIG_MAX_STATE 4
#define UART_LCR 3 /* Out: Line Control Register */
/*
* Note: if the word length is 5 bits (UART_LCR_WLEN5), then setting

View File

@ -320,8 +320,7 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
__FILE__, __LINE__, tty->driver->name, port->count);
spin_lock_irqsave(&port->lock, flags);
if (!tty_hung_up_p(filp))
port->count--;
port->count--;
port->blocked_open++;
spin_unlock_irqrestore(&port->lock, flags);
@ -458,8 +457,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
/*
* If the port is the middle of closing, bail out now
*/
if (tty_hung_up_p(filp) ||
test_bit(ASYNCB_CLOSING, &self->port.flags)) {
if (test_bit(ASYNCB_CLOSING, &self->port.flags)) {
/* Hm, why are we blocking on ASYNC_CLOSING if we
* do return -EAGAIN/-ERESTARTSYS below anyway?