From 9b58bec76e8f80664a849ed788e30503463a8eb8 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Thu, 26 Jun 2014 13:24:33 +0200 Subject: Documentation: devicetree: Update samsung UART bindings The primary purpose of this patch is to add information about (now required) aliases of UART ports. However the documentation currently is heavily outdated and so this patch also takes care of this. Signed-off-by: Tomasz Figa Signed-off-by: Greg Kroah-Hartman --- .../devicetree/bindings/serial/samsung_uart.txt | 52 +++++++++++++++++++--- 1 file changed, 46 insertions(+), 6 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/serial/samsung_uart.txt b/Documentation/devicetree/bindings/serial/samsung_uart.txt index 2c8a17cf5cb5..85e8ee2a17fc 100644 --- a/Documentation/devicetree/bindings/serial/samsung_uart.txt +++ b/Documentation/devicetree/bindings/serial/samsung_uart.txt @@ -1,14 +1,54 @@ * 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 + +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>; + }; -- cgit v1.2.3 From 7d78cbefaa465bbf36e2b4b90d3c196a00f54008 Mon Sep 17 00:00:00 2001 From: Heiko Stübner Date: Mon, 16 Jun 2014 15:25:17 +0200 Subject: serial: 8250_dw: add ability to handle the peripheral clock First try to find the named clock variants then fall back to the already existing handling of a nameless declared baudclk. This also adds the missing documentation for this already existing variant. Signed-off-by: Heiko Stuebner Signed-off-by: Greg Kroah-Hartman --- .../bindings/serial/snps-dw-apb-uart.txt | 31 ++++++++++++++++++++++ drivers/tty/serial/8250/8250_dw.c | 31 +++++++++++++++++++--- 2 files changed, 59 insertions(+), 3 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt index f13f1c5be91c..095ac7172ffe 100644 --- a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt +++ b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt @@ -4,7 +4,15 @@ 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: - reg-shift : quantity to shift the register offsets by. If this property is @@ -23,3 +31,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>; + }; diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index a1450ae6f9c1..c531fa42f838 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -59,6 +59,7 @@ struct dw8250_data { int last_mcr; int line; struct clk *clk; + struct clk *pclk; struct uart_8250_dma dma; }; @@ -359,10 +360,25 @@ 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)) + data->clk = devm_clk_get(&pdev->dev, NULL); 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->pclk)) { + err = clk_prepare_enable(data->pclk); + if (err) { + dev_err(&pdev->dev, "could not enable apb_pclk\n"); + return err; + } } data->dma.rx_chan_id = -1; @@ -408,6 +424,9 @@ static int dw8250_remove(struct platform_device *pdev) serial8250_unregister_port(data->line); + if (!IS_ERR(data->pclk)) + clk_disable_unprepare(data->pclk); + if (!IS_ERR(data->clk)) clk_disable_unprepare(data->clk); @@ -445,6 +464,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; } @@ -452,6 +474,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); -- cgit v1.2.3 From d36f47fa841984691a05ca6477dd26064963048c Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 11 Jul 2014 10:16:45 +0200 Subject: serial: efm32: correct namespacing of location property Olof Johansson pointed out that usually the company name is picked as namespace prefix to specific properties. So expect "energymicro,location" but fall back to the previously introduced name "efm32,location". Cc: Olof Johansson Signed-off-by: Uwe Kleine-König Signed-off-by: Greg Kroah-Hartman --- Documentation/devicetree/bindings/serial/efm32-uart.txt | 4 ++-- drivers/tty/serial/efm32-uart.c | 8 +++++++- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/serial/efm32-uart.txt b/Documentation/devicetree/bindings/serial/efm32-uart.txt index 3ca01336b837..8adbab268ca3 100644 --- a/Documentation/devicetree/bindings/serial/efm32-uart.txt +++ b/Documentation/devicetree/bindings/serial/efm32-uart.txt @@ -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>; }; diff --git a/drivers/tty/serial/efm32-uart.c b/drivers/tty/serial/efm32-uart.c index 7baa34920dbf..55d9c00112cc 100644 --- a/drivers/tty/serial/efm32-uart.c +++ b/drivers/tty/serial/efm32-uart.c @@ -665,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"); -- cgit v1.2.3 From 876496b8cd01b02f7eb561c27aeaf908e4c3f86e Mon Sep 17 00:00:00 2001 From: Jingchang Lu Date: Mon, 14 Jul 2014 17:41:10 +0800 Subject: dt-binding: fsl-lpuart: use exact SoC revision to document binding use exact SoC revision instead of wildcard describing to make the binding more clearer. Signed-off-by: Jingchang Lu Signed-off-by: Greg Kroah-Hartman --- Documentation/devicetree/bindings/serial/fsl-lpuart.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/serial/fsl-lpuart.txt b/Documentation/devicetree/bindings/serial/fsl-lpuart.txt index a1d1205d8185..c95005efbcb8 100644 --- a/Documentation/devicetree/bindings/serial/fsl-lpuart.txt +++ b/Documentation/devicetree/bindings/serial/fsl-lpuart.txt @@ -1,7 +1,11 @@ * Freescale low power universal asynchronous receiver/transmitter (lpuart) Required properties: -- compatible : Should be "fsl,-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 -- cgit v1.2.3 From 135f07c3252dc77d0245714d0b413ecc711cd823 Mon Sep 17 00:00:00 2001 From: Naveen Krishna Chatradhi Date: Mon, 14 Jul 2014 17:07:16 +0530 Subject: serial: samsung: get fifosize via device tree UART modules on some SoCs only differ in the fifosize of each UART channel. Its useless to duplicate the drv_data structure or create a compatible name for such a change. We can get fifosize via the device tree nodes (not mandating it). Also updates the documentation. Signed-off-by: Naveen Krishna Chatradhi Reviewed-by: Tomasz Figa Signed-off-by: Greg Kroah-Hartman --- Documentation/devicetree/bindings/serial/samsung_uart.txt | 4 ++++ drivers/tty/serial/samsung.c | 12 +++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/serial/samsung_uart.txt b/Documentation/devicetree/bindings/serial/samsung_uart.txt index 85e8ee2a17fc..e85f37ec33f0 100644 --- a/Documentation/devicetree/bindings/serial/samsung_uart.txt +++ b/Documentation/devicetree/bindings/serial/samsung_uart.txt @@ -29,6 +29,9 @@ Required properties: [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 @@ -51,4 +54,5 @@ Example: "clk_uart_baud3"; clocks = <&clocks PCLK_UART1>, <&clocks PCLK_UART1>, <&clocks SCLK_UART>; + samsung,uart-fifosize = <16>; }; diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index 6be852d4df6d..e49a9451976e 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c @@ -1295,9 +1295,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[index]; + if (pdev->dev.of_node) + of_property_read_u32(pdev->dev.of_node, + "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++; -- cgit v1.2.3 From aef9a7bd9b676f797dd5cefd43deb30d36b976a9 Mon Sep 17 00:00:00 2001 From: Yoshihiro YUNOMAE Date: Wed, 16 Jul 2014 01:19:36 +0000 Subject: serial/uart/8250: Add tunable RX interrupt trigger I/F of FIFO buffers Add tunable RX interrupt trigger I/F of FIFO buffers. Serial devices are used as not only message communication devices but control or sending communication devices. For the latter uses, normally small data will be exchanged, so user applications want to receive data unit as soon as possible for real-time tendency. If we have a sensor which sends a 1 byte data each time and must control a device based on the sensor feedback, the RX interrupt should be triggered for each data. According to HW specification of serial UART devices, RX interrupt trigger can be changed, but the trigger is hard-coded. For example, RX interrupt trigger in 16550A can be set to 1, 4, 8, or 14 bytes for HW, but current driver sets the trigger to only 8bytes. This patch makes some devices change RX interrupt trigger from userland. - Read current setting # cat /sys/class/tty/ttyS0/rx_trig_bytes 8 - Write user setting # echo 1 > /sys/class/tty/ttyS0/rx_trig_bytes # cat /sys/class/tty/ttyS0/rx_trig_bytes 1 - 16550A and Tegra (1, 4, 8, or 14 bytes) - 16650V2 (8, 16, 24, or 28 bytes) - 16654 (8, 16, 56, or 60 bytes) - 16750 (1, 16, 32, or 56 bytes) Changes in V9: - Use attr_group instead of dev_spec_attr_group of uart_port structure Changes in V8: - Divide this patch from V7's patch based on Greg's comment Changes in V7: - Add Documentation - Change I/F name from rx_int_trig to rx_trig_bytes because the name rx_int_trig is hard to understand how users specify the value Changes in V6: - Move FCR_RX_TRIG_* definition in 8250.h to include/uapi/linux/serial_reg.h, rename those to UART_FCR_R_TRIG_*, and use UART_FCR_TRIGGER_MASK to UART_FCR_R_TRIG_BITS() - Change following function names: convert_fcr2val() => fcr_get_rxtrig_bytes() convert_val2rxtrig() => bytes_to_fcr_rxtrig() - Fix typo in serial8250_do_set_termios() - Delete the verbose error message pr_info() in bytes_to_fcr_rxtrig() - Rename *rx_int_trig/rx_trig* to *rxtrig* for several functions or variables (but UI remains rx_int_trig) - Change the meaningless variable name 'val' to 'bytes' following functions: fcr_get_rxtrig_bytes(), bytes_to_fcr_rxtrig(), do_set_rxtrig(), do_serial8250_set_rxtrig(), and serial8250_set_attr_rxtrig() - Use up->fcr in order to get rxtrig_bytes instead of rx_trig_raw in fcr_get_rxtrig_bytes() - Use conf_type->rxtrig_bytes[0] instead of switch statement for support check in register_dev_spec_attr_grp() - Delete the checking whether a user changed FCR or not when minimum buffer is needed in serial8250_do_set_termios() Changes in V5.1: - Fix FCR_RX_TRIG_MAX_STATE definition Changes in V5: - Support Tegra, 16650V2, 16654, and 16750 - Store default FCR value to up->fcr when the port is first created - Add rx_trig_byte[] in uart_config[] for each device and use rx_trig_byte[] in convert_fcr2val() and convert_val2rxtrig() Changes in V4: - Introduce fifo_bug flag in uart_8250_port structure This is enabled only when parity is enabled and UART_BUG_PARITY is enabled for up->bugs. If this flag is enabled, user cannot set RX trigger. - Return -EOPNOTSUPP when it does not support device at convert_fcr2val() and at convert_val2rxtrig() - Set the nearest lower RX trigger when users input a meaningless value at convert_val2rxtrig() - Check whether p->fcr is existing at serial8250_clear_and_reinit_fifos() - Set fcr = up->fcr in the begging of serial8250_do_set_termios() Changes in V3: - Change I/F from ioctl(2) to sysfs(rx_int_trig) Changed in V2: - Use _IOW for TIOCSFIFORTRIG definition - Pass the interrupt trigger value itself Signed-off-by: Yoshihiro YUNOMAE Signed-off-by: Greg Kroah-Hartman --- Documentation/ABI/testing/sysfs-tty | 16 ++++ drivers/tty/serial/8250/8250.h | 2 + drivers/tty/serial/8250/8250_core.c | 173 ++++++++++++++++++++++++++++++++---- include/linux/serial_8250.h | 2 + include/uapi/linux/serial_reg.h | 5 ++ 5 files changed, 183 insertions(+), 15 deletions(-) (limited to 'Documentation') diff --git a/Documentation/ABI/testing/sysfs-tty b/Documentation/ABI/testing/sysfs-tty index ad22fb0ee765..9eb3c2b6b040 100644 --- a/Documentation/ABI/testing/sysfs-tty +++ b/Documentation/ABI/testing/sysfs-tty @@ -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 +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. diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index 1ebf8538b4fa..1b08c918cd51 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -12,6 +12,7 @@ */ #include +#include #include 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; }; diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 0da01458816e..1d42dba6121d 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -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] = { @@ -530,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); @@ -2256,10 +2257,9 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct uart_8250_port *up = up_to_u8250p(port); - unsigned char cval, fcr = 0; + unsigned char cval; unsigned long flags; unsigned int baud, quot; - int fifo_bug = 0; switch (termios->c_cflag & CSIZE) { case CS5: @@ -2282,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; @@ -2306,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; } } @@ -2442,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); @@ -2640,6 +2640,146 @@ 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 = up_to_u8250p(port); @@ -2687,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 diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h index 730ab4b3d686..f93649e22c43 100644 --- a/include/linux/serial_8250.h +++ b/include/linux/serial_8250.h @@ -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; diff --git a/include/uapi/linux/serial_reg.h b/include/uapi/linux/serial_reg.h index 99b47058816a..df6c9ab6b0cd 100644 --- a/include/uapi/linux/serial_reg.h +++ b/include/uapi/linux/serial_reg.h @@ -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 -- cgit v1.2.3 From 7fe090bf48b522de8cd6fe85e2b3252ed74e74f8 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Wed, 23 Jul 2014 23:33:06 +0800 Subject: serial: 8250_dw: Add optional reset control support The Allwinner A31 and A23 SoCs have a reset controller maintaining the UART in reset by default. This patch adds optional reset support to the driver. Signed-off-by: Chen-Yu Tsai Acked-by: Maxime Ripard Signed-off-by: Greg Kroah-Hartman --- Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt | 1 + drivers/tty/serial/8250/8250_dw.c | 9 +++++++++ 2 files changed, 10 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt index 095ac7172ffe..7f76214f728a 100644 --- a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt +++ b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt @@ -15,6 +15,7 @@ The supplying peripheral clock can also be handled, needing a second property 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 diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index affdcb192aed..501db2f58fd2 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -60,6 +61,7 @@ struct dw8250_data { int line; struct clk *clk; struct clk *pclk; + struct reset_control *rst; struct uart_8250_dma dma; }; @@ -383,6 +385,10 @@ static int dw8250_probe(struct platform_device *pdev) } } + data->rst = devm_reset_control_get_optional(&pdev->dev, NULL); + 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; @@ -426,6 +432,9 @@ 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); -- cgit v1.2.3