* [PATCH] tty: not call tty close in fallback
From: yes @ 2019-01-14 6:56 UTC (permalink / raw)
To: robh, gregkh, jslaby, linux-serial, linux-kernel
From: Li RongQing <lirongqing@baidu.com>
when fail to open tty, tty is not in open status and not need
to call close
Signed-off-by: Li RongQing <lirongqing@baidu.com>
---
drivers/tty/serdev/serdev-ttyport.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/tty/serdev/serdev-ttyport.c b/drivers/tty/serdev/serdev-ttyport.c
index fa1672993b4c..bcc1e27d00de 100644
--- a/drivers/tty/serdev/serdev-ttyport.c
+++ b/drivers/tty/serdev/serdev-ttyport.c
@@ -121,7 +121,7 @@ static int ttyport_open(struct serdev_controller *ctrl)
ret = tty->ops->open(serport->tty, NULL);
if (ret)
- goto err_close;
+ goto err_unlock;
tty_unlock(serport->tty);
@@ -142,8 +142,6 @@ static int ttyport_open(struct serdev_controller *ctrl)
return 0;
-err_close:
- tty->ops->close(tty, NULL);
err_unlock:
tty_unlock(tty);
tty_release_struct(tty, serport->tty_idx);
--
2.16.2
^ permalink raw reply related
* Re: [PATCH] tty: not call tty close in fallback
From: Jiri Slaby @ 2019-01-14 7:20 UTC (permalink / raw)
To: yes, robh, gregkh, linux-kernel, linux-serial
In-Reply-To: <1547448961-9588-1-git-send-email-yes>
On 14. 01. 19, 7:56, yes@hpe.com wrote:
> From: Li RongQing <lirongqing@baidu.com>
>
> when fail to open tty, tty is not in open status and not need
> to call close
But tty drivers are special and expect close even on failed open, right?
See tty_open.
> Signed-off-by: Li RongQing <lirongqing@baidu.com>
> ---
> drivers/tty/serdev/serdev-ttyport.c | 4 +---
> 1 file changed, 1 insertion(+), 3 deletions(-)
>
> diff --git a/drivers/tty/serdev/serdev-ttyport.c b/drivers/tty/serdev/serdev-ttyport.c
> index fa1672993b4c..bcc1e27d00de 100644
> --- a/drivers/tty/serdev/serdev-ttyport.c
> +++ b/drivers/tty/serdev/serdev-ttyport.c
> @@ -121,7 +121,7 @@ static int ttyport_open(struct serdev_controller *ctrl)
>
> ret = tty->ops->open(serport->tty, NULL);
> if (ret)
> - goto err_close;
> + goto err_unlock;
>
> tty_unlock(serport->tty);
>
> @@ -142,8 +142,6 @@ static int ttyport_open(struct serdev_controller *ctrl)
>
> return 0;
>
> -err_close:
> - tty->ops->close(tty, NULL);
> err_unlock:
> tty_unlock(tty);
> tty_release_struct(tty, serport->tty_idx);
>
thanks,
--
js
suse labs
^ permalink raw reply
* Re: [PATCH] tty: not call tty close in fallback
From: Jiri Slaby @ 2019-01-14 7:51 UTC (permalink / raw)
To: lirongqing, robh, gregkh, linux-kernel, linux-serial
In-Reply-To: <1547448961-9588-1-git-send-email-yes>
yes@hpe.com:
550 5.1.1 User Unknown
You are sending e-mails/patches from a non-existant address?
On 14. 01. 19, 7:56, yes@hpe.com wrote:
> From: Li RongQing <lirongqing@baidu.com>
>
> when fail to open tty, tty is not in open status and not need
> to call close
But tty drivers are special and expect close even on failed open, right?
See tty_open.
> Signed-off-by: Li RongQing <lirongqing@baidu.com>
> ---
> drivers/tty/serdev/serdev-ttyport.c | 4 +---
> 1 file changed, 1 insertion(+), 3 deletions(-)
>
> diff --git a/drivers/tty/serdev/serdev-ttyport.c b/drivers/tty/serdev/serdev-ttyport.c
> index fa1672993b4c..bcc1e27d00de 100644
> --- a/drivers/tty/serdev/serdev-ttyport.c
> +++ b/drivers/tty/serdev/serdev-ttyport.c
> @@ -121,7 +121,7 @@ static int ttyport_open(struct serdev_controller *ctrl)
>
> ret = tty->ops->open(serport->tty, NULL);
> if (ret)
> - goto err_close;
> + goto err_unlock;
>
> tty_unlock(serport->tty);
>
> @@ -142,8 +142,6 @@ static int ttyport_open(struct serdev_controller *ctrl)
>
> return 0;
>
> -err_close:
> - tty->ops->close(tty, NULL);
> err_unlock:
> tty_unlock(tty);
> tty_release_struct(tty, serport->tty_idx);
>
thanks,
--
js
suse labs
^ permalink raw reply
* Re: [PATCH 1/2] dt-bindings: serial: Convert snps,dw-apb-uart to json-schema
From: Simon Horman @ 2019-01-14 9:30 UTC (permalink / raw)
To: Rob Herring; +Cc: devicetree, linux-kernel, Greg Kroah-Hartman, linux-serial
In-Reply-To: <20190110222017.6390-1-robh@kernel.org>
On Thu, Jan 10, 2019 at 04:20:16PM -0600, Rob Herring wrote:
> Convert the snps,dw-apb-uart binding to DT schema using json-schema.
>
> The Rockchip and Broadcom compatible strings were not documented,
> so add them here.
I believe the documentation of the Renesas compatible strings is also new
in this file. Perhaps it would be worth mentioning that too.
In any case
Reviewed-by: Simon Horman <horms+renesas@verge.net.au>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: linux-serial@vger.kernel.org
> Signed-off-by: Rob Herring <robh@kernel.org>
> ---
> .../bindings/serial/snps-dw-apb-uart.txt | 76 ----------
> .../bindings/serial/snps-dw-apb-uart.yaml | 140 ++++++++++++++++++
> 2 files changed, 140 insertions(+), 76 deletions(-)
> delete mode 100644 Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt
> create mode 100644 Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
>
> diff --git a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt
> deleted file mode 100644
> index 12bbe9f22560..000000000000
> --- a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt
> +++ /dev/null
> @@ -1,76 +0,0 @@
> -* Synopsys DesignWare ABP UART
> -
> -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:
> -- snps,uart-16550-compatible : reflects the value of UART_16550_COMPATIBLE
> - configuration parameter. Define this if your UART does not implement the busy
> - functionality.
> -- 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
> - performed on the device. If this property is not present then single byte
> - accesses are used.
> -- dcd-override : Override the DCD modem status signal. This signal will always
> - be reported as active instead of being obtained from the modem status
> - register. Define this if your serial port does not use this pin.
> -- dsr-override : Override the DTS modem status signal. This signal will always
> - be reported as active instead of being obtained from the modem status
> - register. Define this if your serial port does not use this pin.
> -- cts-override : Override the CTS modem status signal. This signal will always
> - be reported as active instead of being obtained from the modem status
> - register. Define this if your serial port does not use this pin.
> -- ri-override : Override the RI modem status signal. This signal will always be
> - reported as inactive instead of being obtained from the modem status register.
> - Define this if your serial port does not use this pin.
> -
> -Example:
> -
> - uart@80230000 {
> - compatible = "snps,dw-apb-uart";
> - reg = <0x80230000 0x100>;
> - clock-frequency = <3686400>;
> - interrupts = <10>;
> - reg-shift = <2>;
> - reg-io-width = <4>;
> - dcd-override;
> - dsr-override;
> - cts-override;
> - ri-override;
> - };
> -
> -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/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
> new file mode 100644
> index 000000000000..b42002542690
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
> @@ -0,0 +1,140 @@
> +# SPDX-License-Identifier: GPL-2.0
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/serial/snps-dw-apb-uart.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Synopsys DesignWare ABP UART
> +
> +maintainers:
> + - Rob Herring <robh@kernel.org>
> +
> +allOf:
> + - $ref: /schemas/serial.yaml#
> +
> +properties:
> + compatible:
> + oneOf:
> + - items:
> + - enum:
> + - renesas,r9a06g032-uart
> + - renesas,r9a06g033-uart
> + - const: renesas,rzn1-uart
> + - items:
> + - enum:
> + - rockchip,px30-uart
> + - rockchip,rk3036-uart
> + - rockchip,rk3066-uart
> + - rockchip,rk3188-uart
> + - rockchip,rk3288-uart
> + - rockchip,rk3328-uart
> + - rockchip,rk3368-uart
> + - rockchip,rk3399-uart
> + - rockchip,rv1108-uart
> + - const: snps,dw-apb-uart
> + - items:
> + - enum:
> + - brcm,bcm11351-dw-apb-uart
> + - brcm,bcm21664-dw-apb-uart
> + - const: snps,dw-apb-uart
> + - const: snps,dw-apb-uart
> +
> + reg:
> + maxItems: 1
> +
> + interrupts:
> + maxItems: 1
> +
> + clock-frequency: true
> +
> + clocks:
> + minItems: 1
> + maxItems: 2
> +
> + clock-names:
> + items:
> + - const: baudclk
> + - const: apb_pclk
> +
> + snps,uart-16550-compatible:
> + description: reflects the value of UART_16550_COMPATIBLE configuration
> + parameter. Define this if your UART does not implement the busy functionality.
> + type: boolean
> +
> + resets:
> + maxItems: 1
> +
> + reg-shift: true
> +
> + reg-io-width: true
> +
> + dcd-override:
> + description: Override the DCD modem status signal. This signal will
> + always be reported as active instead of being obtained from the modem
> + status register. Define this if your serial port does not use this
> + pin.
> + type: boolean
> +
> + dsr-override:
> + description: Override the DTS modem status signal. This signal will
> + always be reported as active instead of being obtained from the modem
> + status register. Define this if your serial port does not use this
> + pin.
> + type: boolean
> +
> + cts-override:
> + description: Override the CTS modem status signal. This signal will
> + always be reported as active instead of being obtained from the modem
> + status register. Define this if your serial port does not use this
> + pin.
> + type: boolean
> +
> + ri-override:
> + description: Override the RI modem status signal. This signal will always
> + be reported as inactive instead of being obtained from the modem status
> + register. Define this if your serial port does not use this pin.
> + type: boolean
> +
> +required:
> + - compatible
> + - reg
> + - interrupts
> +
> +examples:
> + - |
> + serial@80230000 {
> + compatible = "snps,dw-apb-uart";
> + reg = <0x80230000 0x100>;
> + clock-frequency = <3686400>;
> + interrupts = <10>;
> + reg-shift = <2>;
> + reg-io-width = <4>;
> + dcd-override;
> + dsr-override;
> + cts-override;
> + ri-override;
> + };
> +
> + - |
> + // Example with one clock:
> + serial@80230000 {
> + compatible = "snps,dw-apb-uart";
> + reg = <0x80230000 0x100>;
> + clocks = <&baudclk>;
> + interrupts = <10>;
> + reg-shift = <2>;
> + reg-io-width = <4>;
> + };
> +
> + - |
> + // Example with two clocks:
> + serial@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>;
> + };
> +...
^ permalink raw reply
* Re: [PATCH 2/2] dt-bindings: serial: Move renesas,rzn1-uart into the snps-dw-apb-uart binding
From: Simon Horman @ 2019-01-14 9:30 UTC (permalink / raw)
To: Rob Herring
Cc: devicetree, linux-kernel, Phil Edworthy, Greg Kroah-Hartman,
linux-serial
In-Reply-To: <20190110222017.6390-2-robh@kernel.org>
On Thu, Jan 10, 2019 at 04:20:17PM -0600, Rob Herring wrote:
> The renesas,rzn1-uart binding only differs in compatible string from the
> snps-dw-apb-uart binding. Move it there, converting it to json-schema in
> the process.
This confused me slightly as this patch removes renesas,rzn1-uart.txt
but doesn't add the renesas bindings elsewhere. I now see that is done
in patch 1/2, which is fine. But it might be worth rewording the changelog.
That notwithstanding:
Reviewed-by: Simon Horman <horms+renesas@verge.net.au>
> Cc: Phil Edworthy <phil.edworthy@renesas.com>
> Cc: Simon Horman <horms+renesas@verge.net.au>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: linux-serial@vger.kernel.org
> Signed-off-by: Rob Herring <robh@kernel.org>
> ---
> .../devicetree/bindings/serial/renesas,rzn1-uart.txt | 10 ----------
> 1 file changed, 10 deletions(-)
> delete mode 100644 Documentation/devicetree/bindings/serial/renesas,rzn1-uart.txt
>
> diff --git a/Documentation/devicetree/bindings/serial/renesas,rzn1-uart.txt b/Documentation/devicetree/bindings/serial/renesas,rzn1-uart.txt
> deleted file mode 100644
> index 8b9e0d4dc2e4..000000000000
> --- a/Documentation/devicetree/bindings/serial/renesas,rzn1-uart.txt
> +++ /dev/null
> @@ -1,10 +0,0 @@
> -Renesas RZ/N1 UART
> -
> -This controller is based on the Synopsys DesignWare ABP UART and inherits all
> -properties defined in snps-dw-apb-uart.txt except for the compatible property.
> -
> -Required properties:
> -- compatible : The device specific string followed by the generic RZ/N1 string.
> - Therefore it must be one of:
> - "renesas,r9a06g032-uart", "renesas,rzn1-uart"
> - "renesas,r9a06g033-uart", "renesas,rzn1-uart"
> --
> 2.19.1
>
^ permalink raw reply
* Re: [PATCH 0/3] serdev support for n_gsm
From: Pavel Machek @ 2019-01-14 9:38 UTC (permalink / raw)
To: Tony Lindgren
Cc: Greg Kroah-Hartman, linux-kernel, Alan Cox, Jiri Slaby,
Johan Hovold, Peter Hurley, Rob Herring, Sebastian Reichel,
linux-serial
In-Reply-To: <20190114012528.2367-1-tony@atomide.com>
[-- Attachment #1: Type: text/plain, Size: 899 bytes --]
On Sun 2019-01-13 17:25:25, Tony Lindgren wrote:
> Hi all,
>
> Here's a series of patches to add initial serdev support to n_gsm
> TS 27.010 line discipline.
>
> This allows handling vendor specific protocols on top of TS 27.010 and
> allows creating simple serdev drivers where it makes sense. So far I've
> tested it with droid 4 for it's modem to provide char devices for AT
> ports, modem PM support, and serdev drivers for GNSS and Alsa ASoC.
>
> I'll be posting the related MFD, GNSS and Alsa ASoC drivers separately.
> For reference, the MFD driver is at [0], the GNSS driver at [1], and
> the Alsa ASoC driver at [2] below.
For the series:
Acked-by: Pavel Machek <pavel@ucw.cz>
Thanks for doing this!
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]
^ permalink raw reply
* [PATCH] 8250_pci.c: Update NI specific devices class to multi serial
From: Guan Yung Tseng @ 2019-01-14 14:10 UTC (permalink / raw)
To: gregkh; +Cc: linux-serial, linux-kernel, Guan Yung Tseng
Modified NI devices class to PCI_CLASS_COMMUNICATION_MULTISERIAL.
The reason of doing this is because all NI multi port serial cards
use PCI_CLASS_COMMUNICATION_OTHER class and thus fail the
serial_pci_is_class_communication test added in the commit 7d8905d06405
("serial: 8250_pci: Enable device after we check black list").
Signed-off-by: Guan Yung Tseng <guan.yung.tseng@ni.com>
---
drivers/tty/serial/8250/8250_pci.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 4986b4a..0949db1 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -663,6 +663,13 @@ static int pci_xircom_init(struct pci_dev *dev)
return 0;
}
+static int pci_ni_probe(struct pci_dev *dev)
+{
+ dev->class = PCI_CLASS_COMMUNICATION_MULTISERIAL << 8 |
+ (dev->class & 0xff);
+ return 0;
+}
+
static int pci_ni8420_init(struct pci_dev *dev)
{
void __iomem *p;
@@ -1850,6 +1857,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.device = PCI_DEVICE_ID_NI_PCI23216,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
+ .probe = pci_ni_probe,
.init = pci_ni8420_init,
.setup = pci_default_setup,
.exit = pci_ni8420_exit,
@@ -1859,6 +1867,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.device = PCI_DEVICE_ID_NI_PCI2328,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
+ .probe = pci_ni_probe,
.init = pci_ni8420_init,
.setup = pci_default_setup,
.exit = pci_ni8420_exit,
@@ -1868,6 +1877,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.device = PCI_DEVICE_ID_NI_PCI2324,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
+ .probe = pci_ni_probe,
.init = pci_ni8420_init,
.setup = pci_default_setup,
.exit = pci_ni8420_exit,
@@ -1877,6 +1887,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.device = PCI_DEVICE_ID_NI_PCI2322,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
+ .probe = pci_ni_probe,
.init = pci_ni8420_init,
.setup = pci_default_setup,
.exit = pci_ni8420_exit,
@@ -1886,6 +1897,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.device = PCI_DEVICE_ID_NI_PCI2324I,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
+ .probe = pci_ni_probe,
.init = pci_ni8420_init,
.setup = pci_default_setup,
.exit = pci_ni8420_exit,
@@ -1895,6 +1907,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.device = PCI_DEVICE_ID_NI_PCI2322I,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
+ .probe = pci_ni_probe,
.init = pci_ni8420_init,
.setup = pci_default_setup,
.exit = pci_ni8420_exit,
@@ -1904,6 +1917,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.device = PCI_DEVICE_ID_NI_PXI8420_23216,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
+ .probe = pci_ni_probe,
.init = pci_ni8420_init,
.setup = pci_default_setup,
.exit = pci_ni8420_exit,
@@ -1913,6 +1927,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.device = PCI_DEVICE_ID_NI_PXI8420_2328,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
+ .probe = pci_ni_probe,
.init = pci_ni8420_init,
.setup = pci_default_setup,
.exit = pci_ni8420_exit,
@@ -1922,6 +1937,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.device = PCI_DEVICE_ID_NI_PXI8420_2324,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
+ .probe = pci_ni_probe,
.init = pci_ni8420_init,
.setup = pci_default_setup,
.exit = pci_ni8420_exit,
@@ -1931,6 +1947,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.device = PCI_DEVICE_ID_NI_PXI8420_2322,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
+ .probe = pci_ni_probe,
.init = pci_ni8420_init,
.setup = pci_default_setup,
.exit = pci_ni8420_exit,
@@ -1940,6 +1957,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.device = PCI_DEVICE_ID_NI_PXI8422_2324,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
+ .probe = pci_ni_probe,
.init = pci_ni8420_init,
.setup = pci_default_setup,
.exit = pci_ni8420_exit,
@@ -1949,6 +1967,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.device = PCI_DEVICE_ID_NI_PXI8422_2322,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
+ .probe = pci_ni_probe,
.init = pci_ni8420_init,
.setup = pci_default_setup,
.exit = pci_ni8420_exit,
@@ -1958,6 +1977,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.device = PCI_ANY_ID,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
+ .probe = pci_ni_probe,
.init = pci_ni8430_init,
.setup = pci_ni8430_setup,
.exit = pci_ni8430_exit,
--
2.7.4
^ permalink raw reply related
* Re: [PATCH 1/2] dt-bindings: serial: Convert snps,dw-apb-uart to json-schema
From: Rob Herring @ 2019-01-14 16:23 UTC (permalink / raw)
To: Simon Horman
Cc: devicetree, linux-kernel@vger.kernel.org, Greg Kroah-Hartman,
open list:SERIAL DRIVERS
In-Reply-To: <20190114093022.hjouckoss2zemefg@verge.net.au>
On Mon, Jan 14, 2019 at 3:30 AM Simon Horman <horms@verge.net.au> wrote:
>
> On Thu, Jan 10, 2019 at 04:20:16PM -0600, Rob Herring wrote:
> > Convert the snps,dw-apb-uart binding to DT schema using json-schema.
> >
> > The Rockchip and Broadcom compatible strings were not documented,
> > so add them here.
>
> I believe the documentation of the Renesas compatible strings is also new
> in this file. Perhaps it would be worth mentioning that too.
Ah, that should be in patch 2. Will respin.
> In any case
>
> Reviewed-by: Simon Horman <horms+renesas@verge.net.au>
>
^ permalink raw reply
* [PATCH] tty: serial: meson: if no alias specified use an available id
From: Loys Ollivier @ 2019-01-14 16:54 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, Kevin Hilman
Cc: Loys Ollivier, linux-serial, linux-arm-kernel, linux-amlogic,
linux-kernel
At probe, the uart driver tries to get an id from a device tree alias.
When no alias was specified, the driver would return an error and probing
would fail.
Providing an alias for registering a serial device should not be mandatory.
If the device tree does not specify an alias, provide an id from a reserved
range so that the probing can continue.
Signed-off-by: Loys Ollivier <lollivier@baylibre.com>
---
drivers/tty/serial/meson_uart.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c
index 8a842591b37c..fbc5bc022a39 100644
--- a/drivers/tty/serial/meson_uart.c
+++ b/drivers/tty/serial/meson_uart.c
@@ -72,7 +72,8 @@
#define AML_UART_BAUD_USE BIT(23)
#define AML_UART_BAUD_XTAL BIT(24)
-#define AML_UART_PORT_NUM 6
+#define AML_UART_PORT_NUM 12
+#define AML_UART_PORT_OFFSET 6
#define AML_UART_DEV_NAME "ttyAML"
@@ -654,10 +655,20 @@ static int meson_uart_probe(struct platform_device *pdev)
struct resource *res_mem, *res_irq;
struct uart_port *port;
int ret = 0;
+ int id = -1;
if (pdev->dev.of_node)
pdev->id = of_alias_get_id(pdev->dev.of_node, "serial");
+ if (pdev->id < 0) {
+ for (id = AML_UART_PORT_OFFSET; id < AML_UART_PORT_NUM; id++) {
+ if (!meson_ports[id]) {
+ pdev->id = id;
+ break;
+ }
+ }
+ }
+
if (pdev->id < 0 || pdev->id >= AML_UART_PORT_NUM)
return -EINVAL;
--
2.7.4
^ permalink raw reply related
* [PATCH v2 1/2] dt-bindings: serial: Convert snps,dw-apb-uart to json-schema
From: Rob Herring @ 2019-01-14 17:29 UTC (permalink / raw)
To: devicetree; +Cc: linux-kernel, Simon Horman, Greg Kroah-Hartman, linux-serial
Convert the snps,dw-apb-uart binding to DT schema using json-schema.
The Rockchip and Broadcom compatible strings were not documented,
so add them here.
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: linux-serial@vger.kernel.org
Reviewed-by: Simon Horman <horms+renesas@verge.net.au>
Signed-off-by: Rob Herring <robh@kernel.org>
---
v2:
- Move Renesas compatible strings to patch 2
.../bindings/serial/snps-dw-apb-uart.txt | 76 ----------
.../bindings/serial/snps-dw-apb-uart.yaml | 135 ++++++++++++++++++
2 files changed, 135 insertions(+), 76 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt
create mode 100644 Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
diff --git a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt
deleted file mode 100644
index 12bbe9f22560..000000000000
--- a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.txt
+++ /dev/null
@@ -1,76 +0,0 @@
-* Synopsys DesignWare ABP UART
-
-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:
-- snps,uart-16550-compatible : reflects the value of UART_16550_COMPATIBLE
- configuration parameter. Define this if your UART does not implement the busy
- functionality.
-- 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
- performed on the device. If this property is not present then single byte
- accesses are used.
-- dcd-override : Override the DCD modem status signal. This signal will always
- be reported as active instead of being obtained from the modem status
- register. Define this if your serial port does not use this pin.
-- dsr-override : Override the DTS modem status signal. This signal will always
- be reported as active instead of being obtained from the modem status
- register. Define this if your serial port does not use this pin.
-- cts-override : Override the CTS modem status signal. This signal will always
- be reported as active instead of being obtained from the modem status
- register. Define this if your serial port does not use this pin.
-- ri-override : Override the RI modem status signal. This signal will always be
- reported as inactive instead of being obtained from the modem status register.
- Define this if your serial port does not use this pin.
-
-Example:
-
- uart@80230000 {
- compatible = "snps,dw-apb-uart";
- reg = <0x80230000 0x100>;
- clock-frequency = <3686400>;
- interrupts = <10>;
- reg-shift = <2>;
- reg-io-width = <4>;
- dcd-override;
- dsr-override;
- cts-override;
- ri-override;
- };
-
-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/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
new file mode 100644
index 000000000000..3e90c790d720
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
@@ -0,0 +1,135 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/serial/snps-dw-apb-uart.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Synopsys DesignWare ABP UART
+
+maintainers:
+ - Rob Herring <robh@kernel.org>
+
+allOf:
+ - $ref: /schemas/serial.yaml#
+
+properties:
+ compatible:
+ oneOf:
+ - items:
+ - enum:
+ - rockchip,px30-uart
+ - rockchip,rk3036-uart
+ - rockchip,rk3066-uart
+ - rockchip,rk3188-uart
+ - rockchip,rk3288-uart
+ - rockchip,rk3328-uart
+ - rockchip,rk3368-uart
+ - rockchip,rk3399-uart
+ - rockchip,rv1108-uart
+ - const: snps,dw-apb-uart
+ - items:
+ - enum:
+ - brcm,bcm11351-dw-apb-uart
+ - brcm,bcm21664-dw-apb-uart
+ - const: snps,dw-apb-uart
+ - const: snps,dw-apb-uart
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ clock-frequency: true
+
+ clocks:
+ minItems: 1
+ maxItems: 2
+
+ clock-names:
+ items:
+ - const: baudclk
+ - const: apb_pclk
+
+ snps,uart-16550-compatible:
+ description: reflects the value of UART_16550_COMPATIBLE configuration
+ parameter. Define this if your UART does not implement the busy functionality.
+ type: boolean
+
+ resets:
+ maxItems: 1
+
+ reg-shift: true
+
+ reg-io-width: true
+
+ dcd-override:
+ description: Override the DCD modem status signal. This signal will
+ always be reported as active instead of being obtained from the modem
+ status register. Define this if your serial port does not use this
+ pin.
+ type: boolean
+
+ dsr-override:
+ description: Override the DTS modem status signal. This signal will
+ always be reported as active instead of being obtained from the modem
+ status register. Define this if your serial port does not use this
+ pin.
+ type: boolean
+
+ cts-override:
+ description: Override the CTS modem status signal. This signal will
+ always be reported as active instead of being obtained from the modem
+ status register. Define this if your serial port does not use this
+ pin.
+ type: boolean
+
+ ri-override:
+ description: Override the RI modem status signal. This signal will always
+ be reported as inactive instead of being obtained from the modem status
+ register. Define this if your serial port does not use this pin.
+ type: boolean
+
+required:
+ - compatible
+ - reg
+ - interrupts
+
+examples:
+ - |
+ serial@80230000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x80230000 0x100>;
+ clock-frequency = <3686400>;
+ interrupts = <10>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ dcd-override;
+ dsr-override;
+ cts-override;
+ ri-override;
+ };
+
+ - |
+ // Example with one clock:
+ serial@80230000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x80230000 0x100>;
+ clocks = <&baudclk>;
+ interrupts = <10>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ };
+
+ - |
+ // Example with two clocks:
+ serial@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>;
+ };
+...
--
2.19.1
^ permalink raw reply related
* [PATCH v2 2/2] dt-bindings: serial: Move renesas,rzn1-uart into the snps-dw-apb-uart binding
From: Rob Herring @ 2019-01-14 17:29 UTC (permalink / raw)
To: devicetree
Cc: linux-kernel, Simon Horman, Phil Edworthy, Greg Kroah-Hartman,
linux-serial
In-Reply-To: <20190114172930.7508-1-robh@kernel.org>
The renesas,rzn1-uart binding only differs in compatible string from the
snps-dw-apb-uart binding. Move it there, converting it to json-schema in
the process.
Cc: Phil Edworthy <phil.edworthy@renesas.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: linux-serial@vger.kernel.org
Reviewed-by: Simon Horman <horms+renesas@verge.net.au>
Signed-off-by: Rob Herring <robh@kernel.org>
---
v2:
- Move Renesas compatible strings to this patch
.../devicetree/bindings/serial/renesas,rzn1-uart.txt | 10 ----------
.../devicetree/bindings/serial/snps-dw-apb-uart.yaml | 5 +++++
2 files changed, 5 insertions(+), 10 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/serial/renesas,rzn1-uart.txt
diff --git a/Documentation/devicetree/bindings/serial/renesas,rzn1-uart.txt b/Documentation/devicetree/bindings/serial/renesas,rzn1-uart.txt
deleted file mode 100644
index 8b9e0d4dc2e4..000000000000
--- a/Documentation/devicetree/bindings/serial/renesas,rzn1-uart.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-Renesas RZ/N1 UART
-
-This controller is based on the Synopsys DesignWare ABP UART and inherits all
-properties defined in snps-dw-apb-uart.txt except for the compatible property.
-
-Required properties:
-- compatible : The device specific string followed by the generic RZ/N1 string.
- Therefore it must be one of:
- "renesas,r9a06g032-uart", "renesas,rzn1-uart"
- "renesas,r9a06g033-uart", "renesas,rzn1-uart"
diff --git a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
index 3e90c790d720..b42002542690 100644
--- a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
+++ b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
@@ -15,6 +15,11 @@ allOf:
properties:
compatible:
oneOf:
+ - items:
+ - enum:
+ - renesas,r9a06g032-uart
+ - renesas,r9a06g033-uart
+ - const: renesas,rzn1-uart
- items:
- enum:
- rockchip,px30-uart
--
2.19.1
^ permalink raw reply related
* Re: [PATCH 1/2] dt-bindings: serial: Convert snps,dw-apb-uart to json-schema
From: Simon Horman @ 2019-01-15 8:02 UTC (permalink / raw)
To: Rob Herring
Cc: devicetree, linux-kernel@vger.kernel.org, Greg Kroah-Hartman,
open list:SERIAL DRIVERS
In-Reply-To: <CAL_JsqJd_kHi+XU7_oe0upg1iJT2rjjEup3YpyrDQA-OhkgKTw@mail.gmail.com>
On Mon, Jan 14, 2019 at 10:23:15AM -0600, Rob Herring wrote:
> On Mon, Jan 14, 2019 at 3:30 AM Simon Horman <horms@verge.net.au> wrote:
> >
> > On Thu, Jan 10, 2019 at 04:20:16PM -0600, Rob Herring wrote:
> > > Convert the snps,dw-apb-uart binding to DT schema using json-schema.
> > >
> > > The Rockchip and Broadcom compatible strings were not documented,
> > > so add them here.
> >
> > I believe the documentation of the Renesas compatible strings is also new
> > in this file. Perhaps it would be worth mentioning that too.
>
> Ah, that should be in patch 2. Will respin.
Thanks!
>
> > In any case
> >
> > Reviewed-by: Simon Horman <horms+renesas@verge.net.au>
> >
>
^ permalink raw reply
* Re: [PATCH] tty: serial: meson: if no alias specified use an available id
From: Neil Armstrong @ 2019-01-15 9:35 UTC (permalink / raw)
To: Loys Ollivier, Greg Kroah-Hartman, Jiri Slaby, Kevin Hilman
Cc: linux-amlogic, linux-arm-kernel, linux-serial, linux-kernel
In-Reply-To: <1547484866-3600-1-git-send-email-lollivier@baylibre.com>
On 14/01/2019 17:54, Loys Ollivier wrote:
> At probe, the uart driver tries to get an id from a device tree alias.
> When no alias was specified, the driver would return an error and probing
> would fail.
>
> Providing an alias for registering a serial device should not be mandatory.
> If the device tree does not specify an alias, provide an id from a reserved
> range so that the probing can continue.
>
> Signed-off-by: Loys Ollivier <lollivier@baylibre.com>
> ---
> drivers/tty/serial/meson_uart.c | 13 ++++++++++++-
> 1 file changed, 12 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c
> index 8a842591b37c..fbc5bc022a39 100644
> --- a/drivers/tty/serial/meson_uart.c
> +++ b/drivers/tty/serial/meson_uart.c
> @@ -72,7 +72,8 @@
> #define AML_UART_BAUD_USE BIT(23)
> #define AML_UART_BAUD_XTAL BIT(24)
>
> -#define AML_UART_PORT_NUM 6
> +#define AML_UART_PORT_NUM 12
> +#define AML_UART_PORT_OFFSET 6
> #define AML_UART_DEV_NAME "ttyAML"
>
>
> @@ -654,10 +655,20 @@ static int meson_uart_probe(struct platform_device *pdev)
> struct resource *res_mem, *res_irq;
> struct uart_port *port;
> int ret = 0;
> + int id = -1;
>
> if (pdev->dev.of_node)
> pdev->id = of_alias_get_id(pdev->dev.of_node, "serial");
>
> + if (pdev->id < 0) {
> + for (id = AML_UART_PORT_OFFSET; id < AML_UART_PORT_NUM; id++) {
> + if (!meson_ports[id]) {
> + pdev->id = id;
> + break;
> + }
> + }
> + }
> +
> if (pdev->id < 0 || pdev->id >= AML_UART_PORT_NUM)
> return -EINVAL;
>
>
This is welcome !
You could also add:
Suggested-by: Rob Herring <robh@kernel.org>
Reviewed-by: Neil Armstrong <narmstrong@baylibre.com>
Neil
^ permalink raw reply
* [PATCH v2] 8250_pci.c: Update NI specific devices class to multi serial
From: Guan Yung Tseng @ 2019-01-15 10:10 UTC (permalink / raw)
To: gregkh; +Cc: linux-serial, linux-kernel, Guan Yung Tseng
Modified NI devices class to PCI_CLASS_COMMUNICATION_MULTISERIAL.
The reason of doing this is because all NI multi port serial cards
use PCI_CLASS_COMMUNICATION_OTHER class and thus fail the
serial_pci_is_class_communication test added in the commit 7d8905d06405
("serial: 8250_pci: Enable device after we check black list").
Signed-off-by: Guan Yung Tseng <guan.yung.tseng@ni.com>
---
Changes in v2:
- added comment to pci_ni_probe function
drivers/tty/serial/8250/8250_pci.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 4986b4a..1f91858 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -663,6 +663,18 @@ static int pci_xircom_init(struct pci_dev *dev)
return 0;
}
+/*
+ * NI Serial devices incorrectly identify themselves
+ * PCI_CLASS_COMMUNICATION_OTHER, instead of what
+ * they really are: PCI_CLASS_COMMUNICATION_MULTISERIAL
+ */
+static int pci_ni_probe(struct pci_dev *dev)
+{
+ dev->class = PCI_CLASS_COMMUNICATION_MULTISERIAL << 8 |
+ (dev->class & 0xff);
+ return 0;
+}
+
static int pci_ni8420_init(struct pci_dev *dev)
{
void __iomem *p;
@@ -1850,6 +1862,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.device = PCI_DEVICE_ID_NI_PCI23216,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
+ .probe = pci_ni_probe,
.init = pci_ni8420_init,
.setup = pci_default_setup,
.exit = pci_ni8420_exit,
@@ -1859,6 +1872,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.device = PCI_DEVICE_ID_NI_PCI2328,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
+ .probe = pci_ni_probe,
.init = pci_ni8420_init,
.setup = pci_default_setup,
.exit = pci_ni8420_exit,
@@ -1868,6 +1882,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.device = PCI_DEVICE_ID_NI_PCI2324,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
+ .probe = pci_ni_probe,
.init = pci_ni8420_init,
.setup = pci_default_setup,
.exit = pci_ni8420_exit,
@@ -1877,6 +1892,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.device = PCI_DEVICE_ID_NI_PCI2322,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
+ .probe = pci_ni_probe,
.init = pci_ni8420_init,
.setup = pci_default_setup,
.exit = pci_ni8420_exit,
@@ -1886,6 +1902,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.device = PCI_DEVICE_ID_NI_PCI2324I,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
+ .probe = pci_ni_probe,
.init = pci_ni8420_init,
.setup = pci_default_setup,
.exit = pci_ni8420_exit,
@@ -1895,6 +1912,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.device = PCI_DEVICE_ID_NI_PCI2322I,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
+ .probe = pci_ni_probe,
.init = pci_ni8420_init,
.setup = pci_default_setup,
.exit = pci_ni8420_exit,
@@ -1904,6 +1922,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.device = PCI_DEVICE_ID_NI_PXI8420_23216,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
+ .probe = pci_ni_probe,
.init = pci_ni8420_init,
.setup = pci_default_setup,
.exit = pci_ni8420_exit,
@@ -1913,6 +1932,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.device = PCI_DEVICE_ID_NI_PXI8420_2328,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
+ .probe = pci_ni_probe,
.init = pci_ni8420_init,
.setup = pci_default_setup,
.exit = pci_ni8420_exit,
@@ -1922,6 +1942,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.device = PCI_DEVICE_ID_NI_PXI8420_2324,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
+ .probe = pci_ni_probe,
.init = pci_ni8420_init,
.setup = pci_default_setup,
.exit = pci_ni8420_exit,
@@ -1931,6 +1952,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.device = PCI_DEVICE_ID_NI_PXI8420_2322,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
+ .probe = pci_ni_probe,
.init = pci_ni8420_init,
.setup = pci_default_setup,
.exit = pci_ni8420_exit,
@@ -1940,6 +1962,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.device = PCI_DEVICE_ID_NI_PXI8422_2324,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
+ .probe = pci_ni_probe,
.init = pci_ni8420_init,
.setup = pci_default_setup,
.exit = pci_ni8420_exit,
@@ -1949,6 +1972,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.device = PCI_DEVICE_ID_NI_PXI8422_2322,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
+ .probe = pci_ni_probe,
.init = pci_ni8420_init,
.setup = pci_default_setup,
.exit = pci_ni8420_exit,
@@ -1958,6 +1982,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.device = PCI_ANY_ID,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
+ .probe = pci_ni_probe,
.init = pci_ni8430_init,
.setup = pci_ni8430_setup,
.exit = pci_ni8430_exit,
--
2.7.4
^ permalink raw reply related
* Re: [PATCH v2] 8250_pci.c: Update NI specific devices class to multi serial
From: Christoph Hellwig @ 2019-01-15 13:31 UTC (permalink / raw)
To: Guan Yung Tseng; +Cc: gregkh, linux-serial, linux-kernel
In-Reply-To: <1547547005-2149-1-git-send-email-guan.yung.tseng@ni.com>
On Tue, Jan 15, 2019 at 06:10:05PM +0800, Guan Yung Tseng wrote:
> +/*
> + * NI Serial devices incorrectly identify themselves
> + * PCI_CLASS_COMMUNICATION_OTHER, instead of what
> + * they really are: PCI_CLASS_COMMUNICATION_MULTISERIAL
> + */
> +static int pci_ni_probe(struct pci_dev *dev)
> +{
> + dev->class = PCI_CLASS_COMMUNICATION_MULTISERIAL << 8 |
> + (dev->class & 0xff);
> + return 0;
> +}
This looks odd. dev->class should just contain the class code read from
config space. I think you need to work around this in the places that
check the classcode instead and add a quirk for these devices.
^ permalink raw reply
* Re: [PATCH] tty/serial: use uart_console_write in the RISC-V SBL early console
From: Christoph Hellwig @ 2019-01-15 13:59 UTC (permalink / raw)
To: Andreas Schwab
Cc: Anup Patel, Rob Herring, Albert Ou, Greg Kroah-Hartman,
Palmer Dabbelt, linux-kernel@vger.kernel.org List,
Christoph Hellwig, Atish Patra, linux-serial, Jiri Slaby,
linux-riscv
In-Reply-To: <mvmsgy0cu9g.fsf_-_@suse.de>
On Thu, Jan 10, 2019 at 06:11:39PM +0100, Andreas Schwab wrote:
> This enables proper NLCR processing.
>
> Suggested-by: Anup Patel <anup@brainfault.org>
> Signed-off-by: Andreas Schwab <schwab@suse.de>
Looks good,
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply
* [PATCH] tty: serial: lpc32xx_hs: fix missing console boot messages
From: Alexandre Belloni @ 2019-01-15 17:18 UTC (permalink / raw)
To: Greg Kroah-Hartman, Vladimir Zapolskiy
Cc: Sylvain Lemieux, Roland Stigge, Jiri Slaby, linux-serial,
linux-arm-kernel, linux-kernel, Alexandre Belloni
When probing the HSUART, it is put in loopback mode in order to prevent a
potential issue that may happen on RX (Errata HSUART.1).
serial_lpc32xx_startup() moves it out of loopback mode but this is too late
to get the kernel boot messages before userspace opens the device.
Also get out of loopback mode in lpc32xx_hsuart_console_setup().
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
---
drivers/tty/serial/lpc32xx_hs.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/tty/serial/lpc32xx_hs.c b/drivers/tty/serial/lpc32xx_hs.c
index d1d73261575b..f4e27d0ad947 100644
--- a/drivers/tty/serial/lpc32xx_hs.c
+++ b/drivers/tty/serial/lpc32xx_hs.c
@@ -151,6 +151,8 @@ static void lpc32xx_hsuart_console_write(struct console *co, const char *s,
local_irq_restore(flags);
}
+static void lpc32xx_loopback_set(resource_size_t mapbase, int state);
+
static int __init lpc32xx_hsuart_console_setup(struct console *co,
char *options)
{
@@ -170,6 +172,8 @@ static int __init lpc32xx_hsuart_console_setup(struct console *co,
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
+ lpc32xx_loopback_set(port->mapbase, 0); /* get out of loopback mode */
+
return uart_set_options(port, co, baud, parity, bits, flow);
}
--
2.20.1
^ permalink raw reply related
* [PATCH] uart: Fix crash in uart_write and uart_put_char
From: samir @ 2019-01-16 18:28 UTC (permalink / raw)
To: gregkh, jslaby; +Cc: linux-serial, linux-kernel, Samir Virmani, Tycho Andersen
From: Samir Virmani <samir@embedur.com>
We were experiencing a crash similar to the one reported as part of
commit:a5ba1d95e46e ("uart: fix race between uart_put_char() and
uart_shutdown()") in our testbed as well. We continue to observe the same
crash after integrating the commit a5ba1d95e46e ("uart: fix race between
uart_put_char() and uart_shutdown()")
On reviewing the change, the port lock should be taken prior to checking for
if (!circ->buf) in fn. __uart_put_char and other fns. that update the buffer
uart_state->xmit.
Traceback:
[11/27/2018 06:24:32.4870] Unable to handle kernel NULL pointer dereference
at virtual address 0000003b
[11/27/2018 06:24:32.4950] PC is at memcpy+0x48/0x180
[11/27/2018 06:24:32.4950] LR is at uart_write+0x74/0x120
[11/27/2018 06:24:32.4950] pc : [<ffffffc0002e6808>]
lr : [<ffffffc0003747cc>] pstate: 000001c5
[11/27/2018 06:24:32.4950] sp : ffffffc076433d30
[11/27/2018 06:24:32.4950] x29: ffffffc076433d30 x28: 0000000000000140
[11/27/2018 06:24:32.4950] x27: ffffffc0009b9d5e x26: ffffffc07ce36580
[11/27/2018 06:24:32.4950] x25: 0000000000000000 x24: 0000000000000140
[11/27/2018 06:24:32.4950] x23: ffffffc000891200 x22: ffffffc01fc34000
[11/27/2018 06:24:32.4950] x21: 0000000000000fff x20: 0000000000000076
[11/27/2018 06:24:32.4950] x19: 0000000000000076 x18: 0000000000000000
[11/27/2018 06:24:32.4950] x17: 000000000047cf08 x16: ffffffc000099e68
[11/27/2018 06:24:32.4950] x15: 0000000000000018 x14: 776d726966205948
[11/27/2018 06:24:32.4950] x13: 50203a6c6974755f x12: 74647075205d3333
[11/27/2018 06:24:32.4950] x11: 3a35323a36203831 x10: 30322f37322f3131
[11/27/2018 06:24:32.4950] x9 : 5b205d303638342e x8 : 746164206f742070
[11/27/2018 06:24:32.4950] x7 : 7520736920657261 x6 : 000000000000003b
[11/27/2018 06:24:32.4950] x5 : 000000000000817a x4 : 0000000000000008
[11/27/2018 06:24:32.4950] x3 : 2f37322f31312a5b x2 : 000000000000006e
[11/27/2018 06:24:32.4950] x1 : ffffffc0009b9cf0 x0 : 000000000000003b
[11/27/2018 06:24:32.4950] CPU2: stopping
[11/27/2018 06:24:32.4950] CPU: 2 PID: 0 Comm: swapper/2 Tainted: P D O 4.1.51 #3
[11/27/2018 06:24:32.4950] Hardware name: Broadcom-v8A (DT)
[11/27/2018 06:24:32.4950] Call trace:
[11/27/2018 06:24:32.4950] [<ffffffc0000883b8>] dump_backtrace+0x0/0x150
[11/27/2018 06:24:32.4950] [<ffffffc00008851c>] show_stack+0x14/0x20
[11/27/2018 06:24:32.4950] [<ffffffc0005ee810>] dump_stack+0x90/0xb0
[11/27/2018 06:24:32.4950] [<ffffffc00008e844>] handle_IPI+0x18c/0x1a0
[11/27/2018 06:24:32.4950] [<ffffffc000080c68>] gic_handle_irq+0x88/0x90
Fixes: a5ba1d95e46e ("uart: fix race between uart_put_char() and
uart_shutdown()")
Signed-off-by: Samir Virmani <samir@embedur.com>
Cc: Tycho Andersen <tycho@tycho.ws>
---
drivers/tty/serial/serial_core.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index c439a5a..bb55db2 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -540,10 +540,12 @@ static int uart_put_char(struct tty_struct *tty, unsigned char c)
int ret = 0;
circ = &state->xmit;
- if (!circ->buf)
+ port = uart_port_lock(state, flags);
+ if (!circ->buf) {
+ uart_port_unlock(port, flags);
return 0;
+ }
- port = uart_port_lock(state, flags);
if (port && uart_circ_chars_free(circ) != 0) {
circ->buf[circ->head] = c;
circ->head = (circ->head + 1) & (UART_XMIT_SIZE - 1);
@@ -576,11 +578,13 @@ static int uart_write(struct tty_struct *tty,
return -EL3HLT;
}
+ port = uart_port_lock(state, flags);
circ = &state->xmit;
- if (!circ->buf)
+ if (!circ->buf) {
+ uart_port_unlock(port, flags);
return 0;
+ }
- port = uart_port_lock(state, flags);
while (port) {
c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);
if (count < c)
--
2.7.4
^ permalink raw reply related
* Re: [PATCH] uart: Fix crash in uart_write and uart_put_char
From: Tycho Andersen @ 2019-01-16 18:40 UTC (permalink / raw)
To: samir; +Cc: gregkh, jslaby, linux-serial, linux-kernel
In-Reply-To: <1547663287-4890-1-git-send-email-samir@embedur.com>
On Wed, Jan 16, 2019 at 10:28:07AM -0800, samir@embedur.com wrote:
> From: Samir Virmani <samir@embedur.com>
>
> We were experiencing a crash similar to the one reported as part of
> commit:a5ba1d95e46e ("uart: fix race between uart_put_char() and
> uart_shutdown()") in our testbed as well. We continue to observe the same
> crash after integrating the commit a5ba1d95e46e ("uart: fix race between
> uart_put_char() and uart_shutdown()")
>
> On reviewing the change, the port lock should be taken prior to checking for
> if (!circ->buf) in fn. __uart_put_char and other fns. that update the buffer
> uart_state->xmit.
>
> Traceback:
>
> [11/27/2018 06:24:32.4870] Unable to handle kernel NULL pointer dereference
> at virtual address 0000003b
>
> [11/27/2018 06:24:32.4950] PC is at memcpy+0x48/0x180
> [11/27/2018 06:24:32.4950] LR is at uart_write+0x74/0x120
> [11/27/2018 06:24:32.4950] pc : [<ffffffc0002e6808>]
> lr : [<ffffffc0003747cc>] pstate: 000001c5
> [11/27/2018 06:24:32.4950] sp : ffffffc076433d30
> [11/27/2018 06:24:32.4950] x29: ffffffc076433d30 x28: 0000000000000140
> [11/27/2018 06:24:32.4950] x27: ffffffc0009b9d5e x26: ffffffc07ce36580
> [11/27/2018 06:24:32.4950] x25: 0000000000000000 x24: 0000000000000140
> [11/27/2018 06:24:32.4950] x23: ffffffc000891200 x22: ffffffc01fc34000
> [11/27/2018 06:24:32.4950] x21: 0000000000000fff x20: 0000000000000076
> [11/27/2018 06:24:32.4950] x19: 0000000000000076 x18: 0000000000000000
> [11/27/2018 06:24:32.4950] x17: 000000000047cf08 x16: ffffffc000099e68
> [11/27/2018 06:24:32.4950] x15: 0000000000000018 x14: 776d726966205948
> [11/27/2018 06:24:32.4950] x13: 50203a6c6974755f x12: 74647075205d3333
> [11/27/2018 06:24:32.4950] x11: 3a35323a36203831 x10: 30322f37322f3131
> [11/27/2018 06:24:32.4950] x9 : 5b205d303638342e x8 : 746164206f742070
> [11/27/2018 06:24:32.4950] x7 : 7520736920657261 x6 : 000000000000003b
> [11/27/2018 06:24:32.4950] x5 : 000000000000817a x4 : 0000000000000008
> [11/27/2018 06:24:32.4950] x3 : 2f37322f31312a5b x2 : 000000000000006e
> [11/27/2018 06:24:32.4950] x1 : ffffffc0009b9cf0 x0 : 000000000000003b
>
> [11/27/2018 06:24:32.4950] CPU2: stopping
> [11/27/2018 06:24:32.4950] CPU: 2 PID: 0 Comm: swapper/2 Tainted: P D O 4.1.51 #3
> [11/27/2018 06:24:32.4950] Hardware name: Broadcom-v8A (DT)
> [11/27/2018 06:24:32.4950] Call trace:
> [11/27/2018 06:24:32.4950] [<ffffffc0000883b8>] dump_backtrace+0x0/0x150
> [11/27/2018 06:24:32.4950] [<ffffffc00008851c>] show_stack+0x14/0x20
> [11/27/2018 06:24:32.4950] [<ffffffc0005ee810>] dump_stack+0x90/0xb0
> [11/27/2018 06:24:32.4950] [<ffffffc00008e844>] handle_IPI+0x18c/0x1a0
> [11/27/2018 06:24:32.4950] [<ffffffc000080c68>] gic_handle_irq+0x88/0x90
>
> Fixes: a5ba1d95e46e ("uart: fix race between uart_put_char() and
> uart_shutdown()")
> Signed-off-by: Samir Virmani <samir@embedur.com>
> Cc: Tycho Andersen <tycho@tycho.ws>
Acked-by: Tycho Andersen <tycho@tycho.ws>
Thanks,
Tycho
^ permalink raw reply
* [PATCH] serial: 8250: Fix serial8250 initialization crash
From: zhe.he @ 2019-01-17 9:00 UTC (permalink / raw)
To: gregkh, jslaby, andriy.shevchenko, bigeasy, Jisheng.Zhang,
darwin.dingel, linux-serial, linux-kernel, zhe.he
From: He Zhe <zhe.he@windriver.com>
The initialization code of interrupt backoff work might reference NULL
pointer and cause the following crash, if no port was found.
[ 10.017727] CPU 0 Unable to handle kernel paging request at virtual address 000001b0, epc == 807088e0, ra == 8070863c
---- snip ----
[ 11.704470] [<807088e0>] serial8250_register_8250_port+0x318/0x4ac
[ 11.747251] [<80708d74>] serial8250_probe+0x148/0x1c0
[ 11.789301] [<80728450>] platform_drv_probe+0x40/0x94
[ 11.830515] [<807264f8>] really_probe+0xf8/0x318
[ 11.870876] [<80726b7c>] __driver_attach+0x110/0x12c
[ 11.910960] [<80724374>] bus_for_each_dev+0x78/0xcc
[ 11.951134] [<80725958>] bus_add_driver+0x200/0x234
[ 11.989756] [<807273d8>] driver_register+0x84/0x148
[ 12.029832] [<80d72f84>] serial8250_init+0x138/0x198
[ 12.070447] [<80100e6c>] do_one_initcall+0x5c/0x2a0
[ 12.110104] [<80d3a208>] kernel_init_freeable+0x370/0x484
[ 12.150722] [<80a49420>] kernel_init+0x10/0xf8
[ 12.191517] [<8010756c>] ret_from_kernel_thread+0x14/0x1c
This patch makes sure the initialization code can be reached only if a port
is found.
Fixes: commit 6d7f677a2afa ("serial: 8250: Rate limit serial port rx interrupts during input overruns")
Signed-off-by: He Zhe <zhe.he@windriver.com>
---
drivers/tty/serial/8250/8250_core.c | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 189ab12..e441221 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -1070,15 +1070,16 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
ret = 0;
}
- }
- /* Initialise interrupt backoff work if required */
- if (up->overrun_backoff_time_ms > 0) {
- uart->overrun_backoff_time_ms = up->overrun_backoff_time_ms;
- INIT_DELAYED_WORK(&uart->overrun_backoff,
- serial_8250_overrun_backoff_work);
- } else {
- uart->overrun_backoff_time_ms = 0;
+ /* Initialise interrupt backoff work if required */
+ if (up->overrun_backoff_time_ms > 0) {
+ uart->overrun_backoff_time_ms =
+ up->overrun_backoff_time_ms;
+ INIT_DELAYED_WORK(&uart->overrun_backoff,
+ serial_8250_overrun_backoff_work);
+ } else {
+ uart->overrun_backoff_time_ms = 0;
+ }
}
mutex_unlock(&serial_mutex);
--
2.7.4
^ permalink raw reply related
* Re: [PATCH] serial: 8250: Fix serial8250 initialization crash
From: Darwin Dingel @ 2019-01-17 19:49 UTC (permalink / raw)
To: zhe.he@windriver.com, gregkh@linuxfoundation.org, jslaby@suse.com,
andriy.shevchenko@linux.intel.com, bigeasy@linutronix.de,
Jisheng.Zhang@synaptics.com, linux-serial@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <1547715619-181299-1-git-send-email-zhe.he@windriver.com>
On 17/01/19 10:00 PM, zhe.he@windriver.com wrote:
> From: He Zhe <zhe.he@windriver.com>
>
> The initialization code of interrupt backoff work might reference NULL
> pointer and cause the following crash, if no port was found.
>
> [ 10.017727] CPU 0 Unable to handle kernel paging request at virtual address 000001b0, epc == 807088e0, ra == 8070863c
> ---- snip ----
> [ 11.704470] [<807088e0>] serial8250_register_8250_port+0x318/0x4ac
> [ 11.747251] [<80708d74>] serial8250_probe+0x148/0x1c0
> [ 11.789301] [<80728450>] platform_drv_probe+0x40/0x94
> [ 11.830515] [<807264f8>] really_probe+0xf8/0x318
> [ 11.870876] [<80726b7c>] __driver_attach+0x110/0x12c
> [ 11.910960] [<80724374>] bus_for_each_dev+0x78/0xcc
> [ 11.951134] [<80725958>] bus_add_driver+0x200/0x234
> [ 11.989756] [<807273d8>] driver_register+0x84/0x148
> [ 12.029832] [<80d72f84>] serial8250_init+0x138/0x198
> [ 12.070447] [<80100e6c>] do_one_initcall+0x5c/0x2a0
> [ 12.110104] [<80d3a208>] kernel_init_freeable+0x370/0x484
> [ 12.150722] [<80a49420>] kernel_init+0x10/0xf8
> [ 12.191517] [<8010756c>] ret_from_kernel_thread+0x14/0x1c
>
> This patch makes sure the initialization code can be reached only if a port
> is found.
>
> Fixes: commit 6d7f677a2afa ("serial: 8250: Rate limit serial port rx interrupts during input overruns")
> Signed-off-by: He Zhe <zhe.he@windriver.com>
> ---
> drivers/tty/serial/8250/8250_core.c | 17 +++++++++--------
> 1 file changed, 9 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
> index 189ab12..e441221 100644
> --- a/drivers/tty/serial/8250/8250_core.c
> +++ b/drivers/tty/serial/8250/8250_core.c
> @@ -1070,15 +1070,16 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
>
> ret = 0;
> }
> - }
>
> - /* Initialise interrupt backoff work if required */
> - if (up->overrun_backoff_time_ms > 0) {
> - uart->overrun_backoff_time_ms = up->overrun_backoff_time_ms;
> - INIT_DELAYED_WORK(&uart->overrun_backoff,
> - serial_8250_overrun_backoff_work);
> - } else {
> - uart->overrun_backoff_time_ms = 0;
> + /* Initialise interrupt backoff work if required */
> + if (up->overrun_backoff_time_ms > 0) {
> + uart->overrun_backoff_time_ms =
> + up->overrun_backoff_time_ms;
> + INIT_DELAYED_WORK(&uart->overrun_backoff,
> + serial_8250_overrun_backoff_work);
> + } else {
> + uart->overrun_backoff_time_ms = 0;
> + }
> }
>
> mutex_unlock(&serial_mutex);
>
Reviewed-by: Darwin Dingel <darwin.dingel@alliedtelesis.co.nz>
I presume this is the same issue reported here:
https://www.spinics.net/lists/linux-serial/msg33114.html
https://lkml.org/lkml/2018/12/22/171
Thanks!
Regards,
Darwin
^ permalink raw reply
* Re: [PATCH] serial: 8250: Fix serial8250 initialization crash
From: Darwin Dingel @ 2019-01-17 20:06 UTC (permalink / raw)
To: zhe.he@windriver.com, gregkh@linuxfoundation.org, jslaby@suse.com,
andriy.shevchenko@linux.intel.com, bigeasy@linutronix.de,
Jisheng.Zhang@synaptics.com, linux-serial@vger.kernel.org,
linux-kernel@vger.kernel.org, colin.king@canonical.com,
dan.carpenter@oracle.com
In-Reply-To: <41c574bfdce7490597079dae8f328661@svr-chch-ex1.atlnz.lc>
On 18/01/19 8:49 AM, Darwin Dingel wrote:
> On 17/01/19 10:00 PM, zhe.he@windriver.com wrote:
>> From: He Zhe <zhe.he@windriver.com>
>>
>> The initialization code of interrupt backoff work might reference NULL
>> pointer and cause the following crash, if no port was found.
>>
>> [ 10.017727] CPU 0 Unable to handle kernel paging request at virtual address 000001b0, epc == 807088e0, ra == 8070863c
>> ---- snip ----
>> [ 11.704470] [<807088e0>] serial8250_register_8250_port+0x318/0x4ac
>> [ 11.747251] [<80708d74>] serial8250_probe+0x148/0x1c0
>> [ 11.789301] [<80728450>] platform_drv_probe+0x40/0x94
>> [ 11.830515] [<807264f8>] really_probe+0xf8/0x318
>> [ 11.870876] [<80726b7c>] __driver_attach+0x110/0x12c
>> [ 11.910960] [<80724374>] bus_for_each_dev+0x78/0xcc
>> [ 11.951134] [<80725958>] bus_add_driver+0x200/0x234
>> [ 11.989756] [<807273d8>] driver_register+0x84/0x148
>> [ 12.029832] [<80d72f84>] serial8250_init+0x138/0x198
>> [ 12.070447] [<80100e6c>] do_one_initcall+0x5c/0x2a0
>> [ 12.110104] [<80d3a208>] kernel_init_freeable+0x370/0x484
>> [ 12.150722] [<80a49420>] kernel_init+0x10/0xf8
>> [ 12.191517] [<8010756c>] ret_from_kernel_thread+0x14/0x1c
>>
>> This patch makes sure the initialization code can be reached only if a port
>> is found.
>>
>> Fixes: commit 6d7f677a2afa ("serial: 8250: Rate limit serial port rx interrupts during input overruns")
>> Signed-off-by: He Zhe <zhe.he@windriver.com>
>> ---
>> drivers/tty/serial/8250/8250_core.c | 17 +++++++++--------
>> 1 file changed, 9 insertions(+), 8 deletions(-)
>>
>> diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
>> index 189ab12..e441221 100644
>> --- a/drivers/tty/serial/8250/8250_core.c
>> +++ b/drivers/tty/serial/8250/8250_core.c
>> @@ -1070,15 +1070,16 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
>>
>> ret = 0;
>> }
>> - }
>>
>> - /* Initialise interrupt backoff work if required */
>> - if (up->overrun_backoff_time_ms > 0) {
>> - uart->overrun_backoff_time_ms = up->overrun_backoff_time_ms;
>> - INIT_DELAYED_WORK(&uart->overrun_backoff,
>> - serial_8250_overrun_backoff_work);
>> - } else {
>> - uart->overrun_backoff_time_ms = 0;
>> + /* Initialise interrupt backoff work if required */
>> + if (up->overrun_backoff_time_ms > 0) {
>> + uart->overrun_backoff_time_ms =
>> + up->overrun_backoff_time_ms;
>> + INIT_DELAYED_WORK(&uart->overrun_backoff,
>> + serial_8250_overrun_backoff_work);
>> + } else {
>> + uart->overrun_backoff_time_ms = 0;
>> + }
>> }
>>
>> mutex_unlock(&serial_mutex);
>>
>
> Reviewed-by: Darwin Dingel <darwin.dingel@alliedtelesis.co.nz>
>
> I presume this is the same issue reported here:
>
> https://www.spinics.net/lists/linux-serial/msg33114.html
> https://lkml.org/lkml/2018/12/22/171
>
>
>
> Thanks!
> Regards,
>
> Darwin
>
Adding Colin and Dan.
Regards,
Darwin
^ permalink raw reply
* [PATCH v10 0/3] add uart DMA function
From: Long Cheng @ 2019-01-18 3:10 UTC (permalink / raw)
To: Vinod Koul, Randy Dunlap, Rob Herring, Mark Rutland, Ryder Lee,
Sean Wang, Nicolas Boichat
Cc: Zhenbao Liu, devicetree, YT Shen, srv_heupstream,
Greg Kroah-Hartman, Sean Wang, linux-kernel, dmaengine,
Long Cheng, linux-mediatek, linux-serial, Jiri Slaby,
Matthias Brugger, Yingjoe Chen, Dan Williams, linux-arm-kernel
In Mediatek SOCs, the uart can support DMA function.
Base on DMA engine formwork, we add the DMA code to support uart. And put the code under drivers/dma/mediatek.
This series contains document bindings, Kconfig to control the function enable or not,
device tree including interrupt and dma device node, the code of UART DMA
Changes compared to v9
-rename dt-bindings file
-remove direction from device_config
-simplified code
Changes compared to v8
-revise missing items
Changes compared to v7:
-modify apdma uart tx
Changes compared to v6:
-Correct spelling
Changes compared to v5:
-move 'requst irqs' to alloc channel
-remove tasklet.
Changes compared to v4:
-modify Kconfig depends on.
Changes compared to v3:
-fix CONFIG_PM, will cause build fail
Changes compared to v2:
-remove unimportant parameters
-instead of cookie, use APIs of virtual channel.
-use of_dma_xlate_by_chan_id.
Changes compared to v1:
-mian revised file, 8250_mtk_dma.c
--parameters renamed for standard
--remove atomic operation
Long Cheng (3):
dmaengine: 8250_mtk_dma: add MediaTek uart DMA support
arm: dts: mt2712: add uart APDMA to device tree
dt-bindings: dma: uart: rename binding
.../devicetree/bindings/dma/8250_mtk_dma.txt | 33 -
.../devicetree/bindings/dma/mtk-uart-apdma.txt | 33 +
arch/arm64/boot/dts/mediatek/mt2712e.dtsi | 51 ++
drivers/dma/mediatek/Kconfig | 11 +
drivers/dma/mediatek/Makefile | 1 +
drivers/dma/mediatek/mtk-uart-apdma.c | 669 ++++++++++++++++++++
6 files changed, 765 insertions(+), 33 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/dma/8250_mtk_dma.txt
create mode 100644 Documentation/devicetree/bindings/dma/mtk-uart-apdma.txt
create mode 100644 drivers/dma/mediatek/mtk-uart-apdma.c
--
1.7.9.5
^ permalink raw reply
* [PATCH v10 1/3] dmaengine: 8250_mtk_dma: add MediaTek uart DMA support
From: Long Cheng @ 2019-01-18 3:10 UTC (permalink / raw)
To: Vinod Koul, Randy Dunlap, Rob Herring, Mark Rutland, Ryder Lee,
Sean Wang, Nicolas Boichat
Cc: Matthias Brugger, Dan Williams, Greg Kroah-Hartman, Jiri Slaby,
Sean Wang, dmaengine, devicetree, linux-arm-kernel,
linux-mediatek, linux-kernel, linux-serial, srv_heupstream,
Yingjoe Chen, YT Shen, Zhenbao Liu, Long Cheng
In-Reply-To: <1547781016-890-1-git-send-email-long.cheng@mediatek.com>
In DMA engine framework, add 8250 uart dma to support MediaTek uart.
If MediaTek uart enabled(SERIAL_8250_MT6577), and want to improve
the performance, can enable the function.
Signed-off-by: Long Cheng <long.cheng@mediatek.com>
---
drivers/dma/mediatek/Kconfig | 11 +
drivers/dma/mediatek/Makefile | 1 +
drivers/dma/mediatek/mtk-uart-apdma.c | 669 +++++++++++++++++++++++++++++++++
3 files changed, 681 insertions(+)
create mode 100644 drivers/dma/mediatek/mtk-uart-apdma.c
diff --git a/drivers/dma/mediatek/Kconfig b/drivers/dma/mediatek/Kconfig
index 680fc05..ac49eb6 100644
--- a/drivers/dma/mediatek/Kconfig
+++ b/drivers/dma/mediatek/Kconfig
@@ -24,3 +24,14 @@ config MTK_CQDMA
This controller provides the channels which is dedicated to
memory-to-memory transfer to offload from CPU.
+
+config MTK_UART_APDMA
+ tristate "MediaTek SoCs APDMA support for UART"
+ depends on OF && SERIAL_8250_MT6577
+ select DMA_ENGINE
+ select DMA_VIRTUAL_CHANNELS
+ help
+ Support for the UART DMA engine found on MediaTek MTK SoCs.
+ When SERIAL_8250_MT6577 is enabled, and if you want to use DMA,
+ you can enable the config. The DMA engine can only be used
+ with MediaTek SoCs.
diff --git a/drivers/dma/mediatek/Makefile b/drivers/dma/mediatek/Makefile
index 41bb381..61a6d29 100644
--- a/drivers/dma/mediatek/Makefile
+++ b/drivers/dma/mediatek/Makefile
@@ -1,2 +1,3 @@
+obj-$(CONFIG_MTK_UART_APDMA) += mtk-uart-apdma.o
obj-$(CONFIG_MTK_HSDMA) += mtk-hsdma.o
obj-$(CONFIG_MTK_CQDMA) += mtk-cqdma.o
diff --git a/drivers/dma/mediatek/mtk-uart-apdma.c b/drivers/dma/mediatek/mtk-uart-apdma.c
new file mode 100644
index 0000000..427db69
--- /dev/null
+++ b/drivers/dma/mediatek/mtk-uart-apdma.c
@@ -0,0 +1,669 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MediaTek Uart APDMA driver.
+ *
+ * Copyright (c) 2018 MediaTek Inc.
+ * Author: Long Cheng <long.cheng@mediatek.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_dma.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include "../virt-dma.h"
+
+/* The default number of virtual channel */
+#define MTK_UART_APDMA_NR_VCHANS 8
+
+#define VFF_EN_B BIT(0)
+#define VFF_STOP_B BIT(0)
+#define VFF_FLUSH_B BIT(0)
+#define VFF_4G_SUPPORT_B BIT(0)
+#define VFF_RX_INT_EN0_B BIT(0) /* rx valid size >= vff thre */
+#define VFF_RX_INT_EN1_B BIT(1)
+#define VFF_TX_INT_EN_B BIT(0) /* tx left size >= vff thre */
+#define VFF_WARM_RST_B BIT(0)
+#define VFF_RX_INT_CLR_B (BIT(0) | BIT(1))
+#define VFF_TX_INT_CLR_B 0
+#define VFF_STOP_CLR_B 0
+#define VFF_INT_EN_CLR_B 0
+#define VFF_4G_SUPPORT_CLR_B 0
+
+/* interrupt trigger level for tx */
+#define VFF_TX_THRE(n) ((n) * 7 / 8)
+/* interrupt trigger level for rx */
+#define VFF_RX_THRE(n) ((n) * 3 / 4)
+
+#define VFF_RING_SIZE 0xffffU
+/* invert this bit when wrap ring head again */
+#define VFF_RING_WRAP 0x10000U
+
+#define VFF_INT_FLAG 0x00
+#define VFF_INT_EN 0x04
+#define VFF_EN 0x08
+#define VFF_RST 0x0c
+#define VFF_STOP 0x10
+#define VFF_FLUSH 0x14
+#define VFF_ADDR 0x1c
+#define VFF_LEN 0x24
+#define VFF_THRE 0x28
+#define VFF_WPT 0x2c
+#define VFF_RPT 0x30
+/* TX: the buffer size HW can read. RX: the buffer size SW can read. */
+#define VFF_VALID_SIZE 0x3c
+/* TX: the buffer size SW can write. RX: the buffer size HW can write. */
+#define VFF_LEFT_SIZE 0x40
+#define VFF_DEBUG_STATUS 0x50
+#define VFF_4G_SUPPORT 0x54
+
+struct mtk_uart_apdmadev {
+ struct dma_device ddev;
+ struct clk *clk;
+ bool support_33bits;
+ unsigned int dma_requests;
+ unsigned int *dma_irq;
+};
+
+struct mtk_uart_apdma_desc {
+ struct virt_dma_desc vd;
+
+ unsigned int avail_len;
+};
+
+struct mtk_chan {
+ struct virt_dma_chan vc;
+ struct dma_slave_config cfg;
+ void __iomem *base;
+ struct mtk_uart_apdma_desc *desc;
+
+ enum dma_transfer_direction dir;
+
+ bool requested;
+
+ unsigned int rx_status;
+};
+
+static inline struct mtk_uart_apdmadev *
+to_mtk_uart_apdma_dev(struct dma_device *d)
+{
+ return container_of(d, struct mtk_uart_apdmadev, ddev);
+}
+
+static inline struct mtk_chan *to_mtk_uart_apdma_chan(struct dma_chan *c)
+{
+ return container_of(c, struct mtk_chan, vc.chan);
+}
+
+static inline struct mtk_uart_apdma_desc *to_mtk_uart_apdma_desc
+ (struct dma_async_tx_descriptor *t)
+{
+ return container_of(t, struct mtk_uart_apdma_desc, vd.tx);
+}
+
+static void mtk_uart_apdma_write(struct mtk_chan *c,
+ unsigned int reg, unsigned int val)
+{
+ writel(val, c->base + reg);
+}
+
+static unsigned int mtk_uart_apdma_read(struct mtk_chan *c, unsigned int reg)
+{
+ return readl(c->base + reg);
+}
+
+static void mtk_uart_apdma_desc_free(struct virt_dma_desc *vd)
+{
+ struct dma_chan *chan = vd->tx.chan;
+ struct mtk_chan *c = to_mtk_uart_apdma_chan(chan);
+
+ kfree(c->desc);
+}
+
+static void mtk_uart_apdma_start_tx(struct mtk_chan *c)
+{
+ unsigned int len, send, left, wpt, d_wpt, tmp;
+ int ret;
+
+ left = mtk_uart_apdma_read(c, VFF_LEFT_SIZE);
+ if (!left) {
+ mtk_uart_apdma_write(c, VFF_INT_EN, VFF_TX_INT_EN_B);
+ return;
+ }
+
+ /* Wait 1sec for flush, can't sleep */
+ ret = readx_poll_timeout(readl, c->base + VFF_FLUSH, tmp,
+ tmp != VFF_FLUSH_B, 0, 1000000);
+ if (ret)
+ dev_warn(c->vc.chan.device->dev, "tx: fail, debug=0x%x\n",
+ mtk_uart_apdma_read(c, VFF_DEBUG_STATUS));
+
+ send = min_t(unsigned int, left, c->desc->avail_len);
+ wpt = mtk_uart_apdma_read(c, VFF_WPT);
+ len = mtk_uart_apdma_read(c, VFF_LEN);
+
+ d_wpt = wpt + send;
+ if ((d_wpt & VFF_RING_SIZE) >= len) {
+ d_wpt = d_wpt - len;
+ d_wpt = d_wpt ^ VFF_RING_WRAP;
+ }
+ mtk_uart_apdma_write(c, VFF_WPT, d_wpt);
+
+ c->desc->avail_len -= send;
+
+ mtk_uart_apdma_write(c, VFF_INT_EN, VFF_TX_INT_EN_B);
+ if (mtk_uart_apdma_read(c, VFF_FLUSH) == 0U)
+ mtk_uart_apdma_write(c, VFF_FLUSH, VFF_FLUSH_B);
+}
+
+static void mtk_uart_apdma_start_rx(struct mtk_chan *c)
+{
+ struct mtk_uart_apdma_desc *d = c->desc;
+ unsigned int len, wg, rg;
+ int cnt;
+
+ if ((mtk_uart_apdma_read(c, VFF_VALID_SIZE) == 0U) ||
+ !d || !vchan_next_desc(&c->vc))
+ return;
+
+ len = mtk_uart_apdma_read(c, VFF_LEN);
+ rg = mtk_uart_apdma_read(c, VFF_RPT);
+ wg = mtk_uart_apdma_read(c, VFF_WPT);
+ cnt = (wg & VFF_RING_SIZE) - (rg & VFF_RING_SIZE);
+ /*
+ * The buffer is ring buffer. If wrap bit different,
+ * represents the start of the next cycle for WPT
+ */
+ if ((rg ^ wg) & VFF_RING_WRAP)
+ cnt += len;
+
+ c->rx_status = cnt;
+ mtk_uart_apdma_write(c, VFF_RPT, wg);
+
+ list_del(&d->vd.node);
+ vchan_cookie_complete(&d->vd);
+}
+
+static irqreturn_t mtk_uart_apdma_irq_handler(int irq, void *dev_id)
+{
+ struct dma_chan *chan = (struct dma_chan *)dev_id;
+ struct mtk_chan *c = to_mtk_uart_apdma_chan(chan);
+ struct mtk_uart_apdma_desc *d;
+ unsigned long flags;
+
+ spin_lock_irqsave(&c->vc.lock, flags);
+ if (c->dir == DMA_DEV_TO_MEM) {
+ mtk_uart_apdma_write(c, VFF_INT_FLAG, VFF_RX_INT_CLR_B);
+ mtk_uart_apdma_start_rx(c);
+ } else if (c->dir == DMA_MEM_TO_DEV) {
+ d = c->desc;
+
+ mtk_uart_apdma_write(c, VFF_INT_FLAG, VFF_TX_INT_CLR_B);
+
+ if (d->avail_len != 0U) {
+ mtk_uart_apdma_start_tx(c);
+ } else {
+ list_del(&d->vd.node);
+ vchan_cookie_complete(&d->vd);
+ }
+ }
+ spin_unlock_irqrestore(&c->vc.lock, flags);
+
+ return IRQ_HANDLED;
+}
+
+static int mtk_uart_apdma_alloc_chan_resources(struct dma_chan *chan)
+{
+ struct mtk_uart_apdmadev *mtkd = to_mtk_uart_apdma_dev(chan->device);
+ struct mtk_chan *c = to_mtk_uart_apdma_chan(chan);
+ unsigned int tmp;
+ int ret;
+
+ pm_runtime_get_sync(mtkd->ddev.dev);
+
+ mtk_uart_apdma_write(c, VFF_ADDR, 0);
+ mtk_uart_apdma_write(c, VFF_THRE, 0);
+ mtk_uart_apdma_write(c, VFF_LEN, 0);
+ mtk_uart_apdma_write(c, VFF_RST, VFF_WARM_RST_B);
+
+ ret = readx_poll_timeout(readl, c->base + VFF_EN, tmp, !tmp, 10, 100);
+ if (ret) {
+ dev_err(chan->device->dev, "dma reset: fail, timeout\n");
+ return ret;
+ }
+
+ if (!c->requested) {
+ c->requested = true;
+ ret = request_irq(mtkd->dma_irq[chan->chan_id],
+ mtk_uart_apdma_irq_handler, IRQF_TRIGGER_NONE,
+ KBUILD_MODNAME, chan);
+ if (ret < 0) {
+ dev_err(chan->device->dev, "Can't request dma IRQ\n");
+ return -EINVAL;
+ }
+ }
+
+ if (mtkd->support_33bits)
+ mtk_uart_apdma_write(c, VFF_4G_SUPPORT, VFF_4G_SUPPORT_CLR_B);
+
+ return ret;
+}
+
+static void mtk_uart_apdma_free_chan_resources(struct dma_chan *chan)
+{
+ struct mtk_uart_apdmadev *mtkd = to_mtk_uart_apdma_dev(chan->device);
+ struct mtk_chan *c = to_mtk_uart_apdma_chan(chan);
+
+ if (c->requested) {
+ c->requested = false;
+ free_irq(mtkd->dma_irq[chan->chan_id], chan);
+ }
+
+ tasklet_kill(&c->vc.task);
+
+ vchan_free_chan_resources(&c->vc);
+
+ pm_runtime_put_sync(mtkd->ddev.dev);
+}
+
+static enum dma_status mtk_uart_apdma_tx_status(struct dma_chan *chan,
+ dma_cookie_t cookie,
+ struct dma_tx_state *txstate)
+{
+ struct mtk_chan *c = to_mtk_uart_apdma_chan(chan);
+ enum dma_status ret;
+ unsigned long flags;
+
+ if (!txstate)
+ return DMA_ERROR;
+
+ ret = dma_cookie_status(chan, cookie, txstate);
+ spin_lock_irqsave(&c->vc.lock, flags);
+ if (ret == DMA_IN_PROGRESS) {
+ c->rx_status = mtk_uart_apdma_read(c, VFF_RPT) & VFF_RING_SIZE;
+ dma_set_residue(txstate, c->rx_status);
+ } else if (ret == DMA_COMPLETE && c->dir == DMA_DEV_TO_MEM) {
+ dma_set_residue(txstate, c->rx_status);
+ } else {
+ dma_set_residue(txstate, 0);
+ }
+ spin_unlock_irqrestore(&c->vc.lock, flags);
+
+ return ret;
+}
+
+static void mtk_uart_apdma_config_write(struct dma_chan *chan,
+ struct dma_slave_config *cfg,
+ enum dma_transfer_direction dir)
+{
+ struct mtk_chan *c = to_mtk_uart_apdma_chan(chan);
+ struct mtk_uart_apdmadev *mtkd =
+ to_mtk_uart_apdma_dev(c->vc.chan.device);
+ unsigned int tmp;
+
+ if (mtk_uart_apdma_read(c, VFF_EN) == VFF_EN_B)
+ return;
+
+ c->dir = dir;
+
+ if (dir == DMA_DEV_TO_MEM) {
+ tmp = cfg->src_addr_width * 1024;
+
+ mtk_uart_apdma_write(c, VFF_ADDR, cfg->src_addr);
+ mtk_uart_apdma_write(c, VFF_LEN, tmp);
+ mtk_uart_apdma_write(c, VFF_THRE, VFF_RX_THRE(tmp));
+ mtk_uart_apdma_write(c, VFF_INT_EN,
+ VFF_RX_INT_EN0_B | VFF_RX_INT_EN1_B);
+ mtk_uart_apdma_write(c, VFF_RPT, 0);
+ mtk_uart_apdma_write(c, VFF_INT_FLAG, VFF_RX_INT_CLR_B);
+ } else if (dir == DMA_MEM_TO_DEV) {
+ tmp = cfg->dst_addr_width * 1024;
+
+ mtk_uart_apdma_write(c, VFF_ADDR, cfg->dst_addr);
+ mtk_uart_apdma_write(c, VFF_LEN, tmp);
+ mtk_uart_apdma_write(c, VFF_THRE, VFF_TX_THRE(tmp));
+ mtk_uart_apdma_write(c, VFF_WPT, 0);
+ mtk_uart_apdma_write(c, VFF_INT_FLAG, VFF_TX_INT_CLR_B);
+ }
+
+ mtk_uart_apdma_write(c, VFF_EN, VFF_EN_B);
+
+ if (mtkd->support_33bits)
+ mtk_uart_apdma_write(c, VFF_4G_SUPPORT, VFF_4G_SUPPORT_B);
+
+ if (mtk_uart_apdma_read(c, VFF_EN) != VFF_EN_B)
+ dev_err(chan->device->dev, "dir[%d] fail\n", dir);
+}
+
+/*
+ * dmaengine_prep_slave_single will call the function. and sglen is 1.
+ * 8250 uart using one ring buffer, and deal with one sg.
+ */
+static struct dma_async_tx_descriptor *mtk_uart_apdma_prep_slave_sg
+ (struct dma_chan *chan, struct scatterlist *sgl,
+ unsigned int sglen, enum dma_transfer_direction dir,
+ unsigned long tx_flags, void *context)
+{
+ struct mtk_chan *c = to_mtk_uart_apdma_chan(chan);
+ struct mtk_uart_apdma_desc *d;
+
+ if (!is_slave_direction(dir))
+ return NULL;
+
+ mtk_uart_apdma_config_write(chan, &c->cfg, dir);
+
+ /* Now allocate and setup the descriptor */
+ d = kzalloc(sizeof(*d), GFP_ATOMIC);
+ if (!d)
+ return NULL;
+
+ /* sglen is 1 */
+ d->avail_len = sg_dma_len(sgl);
+
+ return vchan_tx_prep(&c->vc, &d->vd, tx_flags);
+}
+
+static void mtk_uart_apdma_issue_pending(struct dma_chan *chan)
+{
+ struct mtk_chan *c = to_mtk_uart_apdma_chan(chan);
+ struct virt_dma_desc *vd;
+ unsigned long flags;
+
+ spin_lock_irqsave(&c->vc.lock, flags);
+ if (vchan_issue_pending(&c->vc)) {
+ vd = vchan_next_desc(&c->vc);
+ c->desc = to_mtk_uart_apdma_desc(&vd->tx);
+ }
+
+ if (c->dir == DMA_DEV_TO_MEM)
+ mtk_uart_apdma_start_rx(c);
+ else if (c->dir == DMA_MEM_TO_DEV)
+ mtk_uart_apdma_start_tx(c);
+
+ spin_unlock_irqrestore(&c->vc.lock, flags);
+}
+
+static int mtk_uart_apdma_slave_config(struct dma_chan *chan,
+ struct dma_slave_config *config)
+{
+ struct mtk_chan *c = to_mtk_uart_apdma_chan(chan);
+
+ memcpy(&c->cfg, config, sizeof(*config));
+
+ return 0;
+}
+
+static int mtk_uart_apdma_terminate_all(struct dma_chan *chan)
+{
+ struct mtk_chan *c = to_mtk_uart_apdma_chan(chan);
+ unsigned long flags;
+ unsigned int tmp;
+ int ret;
+
+ spin_lock_irqsave(&c->vc.lock, flags);
+
+ mtk_uart_apdma_write(c, VFF_FLUSH, VFF_FLUSH_B);
+ /* Wait 1sec for flush, can't sleep */
+ ret = readx_poll_timeout(readl, c->base + VFF_FLUSH, tmp,
+ tmp != VFF_FLUSH_B, 0, 1000000);
+ if (ret)
+ dev_err(c->vc.chan.device->dev, "flush: fail, debug=0x%x\n",
+ mtk_uart_apdma_read(c, VFF_DEBUG_STATUS));
+
+ /* set stop as 1 -> wait until en is 0 -> set stop as 0 */
+ mtk_uart_apdma_write(c, VFF_STOP, VFF_STOP_B);
+ ret = readx_poll_timeout(readl, c->base + VFF_EN, tmp, !tmp, 10, 100);
+ if (ret)
+ dev_err(c->vc.chan.device->dev, "stop: fail, debug=0x%x\n",
+ mtk_uart_apdma_read(c, VFF_DEBUG_STATUS));
+
+ mtk_uart_apdma_write(c, VFF_STOP, VFF_STOP_CLR_B);
+ mtk_uart_apdma_write(c, VFF_INT_EN, VFF_INT_EN_CLR_B);
+
+ if (c->dir == DMA_DEV_TO_MEM)
+ mtk_uart_apdma_write(c, VFF_INT_FLAG, VFF_RX_INT_CLR_B);
+ else if (c->dir == DMA_MEM_TO_DEV)
+ mtk_uart_apdma_write(c, VFF_INT_FLAG, VFF_TX_INT_CLR_B);
+
+ spin_unlock_irqrestore(&c->vc.lock, flags);
+
+ return 0;
+}
+
+static int mtk_uart_apdma_device_pause(struct dma_chan *chan)
+{
+ /* just for check caps pass */
+ return 0;
+}
+
+static void mtk_uart_apdma_free(struct mtk_uart_apdmadev *mtkd)
+{
+ while (!list_empty(&mtkd->ddev.channels)) {
+ struct mtk_chan *c = list_first_entry(&mtkd->ddev.channels,
+ struct mtk_chan, vc.chan.device_node);
+
+ list_del(&c->vc.chan.device_node);
+ tasklet_kill(&c->vc.task);
+ }
+}
+
+static const struct of_device_id mtk_uart_apdma_match[] = {
+ { .compatible = "mediatek,mt6577-uart-dma", },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, mtk_uart_apdma_match);
+
+static int mtk_uart_apdma_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct mtk_uart_apdmadev *mtkd;
+ struct resource *res;
+ struct mtk_chan *c;
+ int bit_mask = 32, rc;
+ unsigned int i;
+
+ mtkd = devm_kzalloc(&pdev->dev, sizeof(*mtkd), GFP_KERNEL);
+ if (!mtkd)
+ return -ENOMEM;
+
+ mtkd->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(mtkd->clk)) {
+ dev_err(&pdev->dev, "No clock specified\n");
+ rc = PTR_ERR(mtkd->clk);
+ return rc;
+ }
+
+ if (of_property_read_bool(np, "dma-33bits"))
+ mtkd->support_33bits = true;
+
+ if (mtkd->support_33bits)
+ bit_mask = 33;
+
+ rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(bit_mask));
+ if (rc)
+ return rc;
+
+ dma_cap_set(DMA_SLAVE, mtkd->ddev.cap_mask);
+ mtkd->ddev.device_alloc_chan_resources =
+ mtk_uart_apdma_alloc_chan_resources;
+ mtkd->ddev.device_free_chan_resources =
+ mtk_uart_apdma_free_chan_resources;
+ mtkd->ddev.device_tx_status = mtk_uart_apdma_tx_status;
+ mtkd->ddev.device_issue_pending = mtk_uart_apdma_issue_pending;
+ mtkd->ddev.device_prep_slave_sg = mtk_uart_apdma_prep_slave_sg;
+ mtkd->ddev.device_config = mtk_uart_apdma_slave_config;
+ mtkd->ddev.device_pause = mtk_uart_apdma_device_pause;
+ mtkd->ddev.device_terminate_all = mtk_uart_apdma_terminate_all;
+ mtkd->ddev.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE);
+ mtkd->ddev.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE);
+ mtkd->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
+ mtkd->ddev.residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT;
+ mtkd->ddev.dev = &pdev->dev;
+ INIT_LIST_HEAD(&mtkd->ddev.channels);
+
+ mtkd->dma_requests = MTK_UART_APDMA_NR_VCHANS;
+ if (of_property_read_u32(np, "dma-requests", &mtkd->dma_requests)) {
+ dev_info(&pdev->dev,
+ "Using %u as missing dma-requests property\n",
+ MTK_UART_APDMA_NR_VCHANS);
+ }
+
+ mtkd->dma_irq = devm_kcalloc(&pdev->dev, mtkd->dma_requests,
+ sizeof(*mtkd->dma_irq), GFP_KERNEL);
+ if (!mtkd->dma_irq)
+ return -ENOMEM;
+
+ for (i = 0; i < mtkd->dma_requests; i++) {
+ c = devm_kzalloc(mtkd->ddev.dev, sizeof(*c), GFP_KERNEL);
+ if (!c) {
+ rc = -ENODEV;
+ goto err_no_dma;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+ if (!res) {
+ rc = -ENODEV;
+ goto err_no_dma;
+ }
+
+ c->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(c->base)) {
+ rc = PTR_ERR(c->base);
+ goto err_no_dma;
+ }
+ c->requested = false;
+ c->vc.desc_free = mtk_uart_apdma_desc_free;
+ vchan_init(&c->vc, &mtkd->ddev);
+
+ mtkd->dma_irq[i] = platform_get_irq(pdev, i);
+ if ((int)mtkd->dma_irq[i] < 0) {
+ dev_err(&pdev->dev, "failed to get IRQ[%d]\n", i);
+ rc = -EINVAL;
+ goto err_no_dma;
+ }
+ }
+
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_set_active(&pdev->dev);
+
+ rc = dma_async_device_register(&mtkd->ddev);
+ if (rc)
+ goto rpm_disable;
+
+ platform_set_drvdata(pdev, mtkd);
+
+ /* Device-tree DMA controller registration */
+ rc = of_dma_controller_register(np, of_dma_xlate_by_chan_id, mtkd);
+ if (rc)
+ goto dma_remove;
+
+ return rc;
+
+dma_remove:
+ dma_async_device_unregister(&mtkd->ddev);
+rpm_disable:
+ pm_runtime_disable(&pdev->dev);
+err_no_dma:
+ mtk_uart_apdma_free(mtkd);
+ return rc;
+}
+
+static int mtk_uart_apdma_remove(struct platform_device *pdev)
+{
+ struct mtk_uart_apdmadev *mtkd = platform_get_drvdata(pdev);
+
+ if (pdev->dev.of_node)
+ of_dma_controller_free(pdev->dev.of_node);
+
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+
+ dma_async_device_unregister(&mtkd->ddev);
+ mtk_uart_apdma_free(mtkd);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int mtk_uart_apdma_suspend(struct device *dev)
+{
+ struct mtk_uart_apdmadev *mtkd = dev_get_drvdata(dev);
+
+ if (!pm_runtime_suspended(dev))
+ clk_disable_unprepare(mtkd->clk);
+
+ return 0;
+}
+
+static int mtk_uart_apdma_resume(struct device *dev)
+{
+ int ret;
+ struct mtk_uart_apdmadev *mtkd = dev_get_drvdata(dev);
+
+ if (!pm_runtime_suspended(dev)) {
+ ret = clk_prepare_enable(mtkd->clk);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+#ifdef CONFIG_PM
+static int mtk_uart_apdma_runtime_suspend(struct device *dev)
+{
+ struct mtk_uart_apdmadev *mtkd = dev_get_drvdata(dev);
+
+ clk_disable_unprepare(mtkd->clk);
+
+ return 0;
+}
+
+static int mtk_uart_apdma_runtime_resume(struct device *dev)
+{
+ int ret;
+ struct mtk_uart_apdmadev *mtkd = dev_get_drvdata(dev);
+
+ ret = clk_prepare_enable(mtkd->clk);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+#endif /* CONFIG_PM */
+
+static const struct dev_pm_ops mtk_uart_apdma_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(mtk_uart_apdma_suspend, mtk_uart_apdma_resume)
+ SET_RUNTIME_PM_OPS(mtk_uart_apdma_runtime_suspend,
+ mtk_uart_apdma_runtime_resume, NULL)
+};
+
+static struct platform_driver mtk_uart_apdma_driver = {
+ .probe = mtk_uart_apdma_probe,
+ .remove = mtk_uart_apdma_remove,
+ .driver = {
+ .name = KBUILD_MODNAME,
+ .pm = &mtk_uart_apdma_pm_ops,
+ .of_match_table = of_match_ptr(mtk_uart_apdma_match),
+ },
+};
+
+module_platform_driver(mtk_uart_apdma_driver);
+
+MODULE_DESCRIPTION("MediaTek UART APDMA Controller Driver");
+MODULE_AUTHOR("Long Cheng <long.cheng@mediatek.com>");
+MODULE_LICENSE("GPL v2");
+
--
1.7.9.5
^ permalink raw reply related
* [PATCH v10 2/3] arm: dts: mt2712: add uart APDMA to device tree
From: Long Cheng @ 2019-01-18 3:10 UTC (permalink / raw)
To: Vinod Koul, Randy Dunlap, Rob Herring, Mark Rutland, Ryder Lee,
Sean Wang, Nicolas Boichat
Cc: Matthias Brugger, Dan Williams, Greg Kroah-Hartman, Jiri Slaby,
Sean Wang, dmaengine, devicetree, linux-arm-kernel,
linux-mediatek, linux-kernel, linux-serial, srv_heupstream,
Yingjoe Chen, YT Shen, Zhenbao Liu, Long Cheng
In-Reply-To: <1547781016-890-1-git-send-email-long.cheng@mediatek.com>
1. add uart APDMA controller device node
2. add uart 0/1/2/3/4/5 DMA function
Signed-off-by: Long Cheng <long.cheng@mediatek.com>
---
arch/arm64/boot/dts/mediatek/mt2712e.dtsi | 51 +++++++++++++++++++++++++++++
1 file changed, 51 insertions(+)
diff --git a/arch/arm64/boot/dts/mediatek/mt2712e.dtsi b/arch/arm64/boot/dts/mediatek/mt2712e.dtsi
index ee627a7..3469a6c 100644
--- a/arch/arm64/boot/dts/mediatek/mt2712e.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt2712e.dtsi
@@ -298,6 +298,9 @@
interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_LOW>;
clocks = <&baud_clk>, <&sys_clk>;
clock-names = "baud", "bus";
+ dmas = <&apdma 10
+ &apdma 11>;
+ dma-names = "tx", "rx";
status = "disabled";
};
@@ -346,6 +349,39 @@
(GIC_CPU_MASK_RAW(0x13) | IRQ_TYPE_LEVEL_HIGH)>;
};
+ apdma: dma-controller@11000400 {
+ compatible = "mediatek,mt2712-uart-dma",
+ "mediatek,mt6577-uart-dma";
+ reg = <0 0x11000400 0 0x80>,
+ <0 0x11000480 0 0x80>,
+ <0 0x11000500 0 0x80>,
+ <0 0x11000580 0 0x80>,
+ <0 0x11000600 0 0x80>,
+ <0 0x11000680 0 0x80>,
+ <0 0x11000700 0 0x80>,
+ <0 0x11000780 0 0x80>,
+ <0 0x11000800 0 0x80>,
+ <0 0x11000880 0 0x80>,
+ <0 0x11000900 0 0x80>,
+ <0 0x11000980 0 0x80>;
+ interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 104 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 105 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 106 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 107 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 108 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 109 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 110 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 111 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 112 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 113 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 114 IRQ_TYPE_LEVEL_LOW>;
+ dma-requests = <12>;
+ clocks = <&pericfg CLK_PERI_AP_DMA>;
+ clock-names = "apdma";
+ #dma-cells = <1>;
+ };
+
auxadc: adc@11001000 {
compatible = "mediatek,mt2712-auxadc";
reg = <0 0x11001000 0 0x1000>;
@@ -362,6 +398,9 @@
interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_LOW>;
clocks = <&baud_clk>, <&sys_clk>;
clock-names = "baud", "bus";
+ dmas = <&apdma 0
+ &apdma 1>;
+ dma-names = "tx", "rx";
status = "disabled";
};
@@ -372,6 +411,9 @@
interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_LOW>;
clocks = <&baud_clk>, <&sys_clk>;
clock-names = "baud", "bus";
+ dmas = <&apdma 2
+ &apdma 3>;
+ dma-names = "tx", "rx";
status = "disabled";
};
@@ -382,6 +424,9 @@
interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_LOW>;
clocks = <&baud_clk>, <&sys_clk>;
clock-names = "baud", "bus";
+ dmas = <&apdma 4
+ &apdma 5>;
+ dma-names = "tx", "rx";
status = "disabled";
};
@@ -392,6 +437,9 @@
interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_LOW>;
clocks = <&baud_clk>, <&sys_clk>;
clock-names = "baud", "bus";
+ dmas = <&apdma 6
+ &apdma 7>;
+ dma-names = "tx", "rx";
status = "disabled";
};
@@ -402,6 +450,9 @@
interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_LOW>;
clocks = <&baud_clk>, <&sys_clk>;
clock-names = "baud", "bus";
+ dmas = <&apdma 8
+ &apdma 9>;
+ dma-names = "tx", "rx";
status = "disabled";
};
--
1.7.9.5
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox