* Re: [PATCH 2/2 v5] tty/serial/8250: use mctrl_gpio helpers
From: Andy Shevchenko @ 2019-06-11 14:48 UTC (permalink / raw)
To: Stefan Roese
Cc: linux-serial, linux-kernel, Yegor Yefremov, Mika Westerberg,
Giulio Benetti, Greg Kroah-Hartman
In-Reply-To: <85f0d39c-e5d8-320b-e611-d956630a629f@denx.de>
On Tue, Jun 11, 2019 at 04:02:54PM +0200, Stefan Roese wrote:
> On 11.06.19 14:44, Andy Shevchenko wrote:
> > On Tue, Jun 11, 2019 at 12:56:03PM +0200, Stefan Roese wrote:
> > > static inline void serial8250_out_MCR(struct uart_8250_port *up, int value)
> > > {
> > > serial_out(up, UART_MCR, value);
> > > +
> > > + if (up->gpios) {
> > > + int mctrl_gpio = 0;
> > > +
> > > + if (value & UART_MCR_RTS)
> > > + mctrl_gpio |= TIOCM_RTS;
> > > + if (value & UART_MCR_DTR)
> > > + mctrl_gpio |= TIOCM_DTR;
> > > +
> > > + mctrl_gpio_set(up->gpios, mctrl_gpio);
> > > + }
> > > }
> > > static inline int serial8250_in_MCR(struct uart_8250_port *up)
> > > {
> > > - return serial_in(up, UART_MCR);
> > > + int mctrl;
> > > +
> > > + mctrl = serial_in(up, UART_MCR);
> > > +
> > > + if (up->gpios) {
> > > + int mctrl_gpio = 0;
> > > +
> > > + /* save current MCR values */
> > > + if (mctrl & UART_MCR_RTS)
> > > + mctrl_gpio |= TIOCM_RTS;
> > > + if (mctrl & UART_MCR_DTR)
> > > + mctrl_gpio |= TIOCM_DTR;
> > > +
> > > + mctrl_gpio = mctrl_gpio_get_outputs(up->gpios, &mctrl_gpio);
> > > + if (mctrl_gpio & TIOCM_RTS)
> > > + mctrl |= UART_MCR_RTS;
> > > + else
> > > + mctrl &= ~UART_MCR_RTS;
> > > +
> > > + if (mctrl_gpio & TIOCM_DTR)
> > > + mctrl |= UART_MCR_DTR;
> > > + else
> > > + mctrl &= ~UART_MCR_DTR;
> > > + }
> > > +
> > > + return mctrl;
> > > }
> >
> > These are using OR logic with potentially volatile data. Shouldn't we mask
> > unused bits in UART_MCR in case of up->gpios != NULL?
>
> Sorry, I don't see, which bits you are referring to? Could you please be
> a bit more specific with the variable / macro meant (example)?
I meant that we double write values in the out() which might have some
consequences, though I hope nothing wrong with it happens.
In the in() we read the all bits in the register.
As now I look at the implementation of mctrl_gpio_get_outputs(),
I think we rather get helpers for conversion between TIOCM and UART_MCR values,
so, they can be used in get_mctrl() / set_mctrl() and above.
The logic now is understandable to me (I was confused by the conversions here
and there).
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH 2/2 v5] tty/serial/8250: use mctrl_gpio helpers
From: Stefan Roese @ 2019-06-11 14:02 UTC (permalink / raw)
To: Andy Shevchenko
Cc: linux-serial, linux-kernel, Yegor Yefremov, Mika Westerberg,
Giulio Benetti, Greg Kroah-Hartman
In-Reply-To: <20190611124415.GT9224@smile.fi.intel.com>
On 11.06.19 14:44, Andy Shevchenko wrote:
> On Tue, Jun 11, 2019 at 12:56:03PM +0200, Stefan Roese wrote:
>> From: Yegor Yefremov <yegorslists@googlemail.com>
>>
>> This patch permits the usage for GPIOs to control
>> the CTS/RTS/DTR/DSR/DCD/RI signals.
>
>> static inline void serial8250_out_MCR(struct uart_8250_port *up, int value)
>> {
>> serial_out(up, UART_MCR, value);
>> +
>> + if (up->gpios) {
>> + int mctrl_gpio = 0;
>> +
>> + if (value & UART_MCR_RTS)
>> + mctrl_gpio |= TIOCM_RTS;
>> + if (value & UART_MCR_DTR)
>> + mctrl_gpio |= TIOCM_DTR;
>> +
>> + mctrl_gpio_set(up->gpios, mctrl_gpio);
>> + }
>> }
>>
>> static inline int serial8250_in_MCR(struct uart_8250_port *up)
>> {
>> - return serial_in(up, UART_MCR);
>> + int mctrl;
>> +
>> + mctrl = serial_in(up, UART_MCR);
>> +
>> + if (up->gpios) {
>> + int mctrl_gpio = 0;
>> +
>> + /* save current MCR values */
>> + if (mctrl & UART_MCR_RTS)
>> + mctrl_gpio |= TIOCM_RTS;
>> + if (mctrl & UART_MCR_DTR)
>> + mctrl_gpio |= TIOCM_DTR;
>> +
>> + mctrl_gpio = mctrl_gpio_get_outputs(up->gpios, &mctrl_gpio);
>> + if (mctrl_gpio & TIOCM_RTS)
>> + mctrl |= UART_MCR_RTS;
>> + else
>> + mctrl &= ~UART_MCR_RTS;
>> +
>> + if (mctrl_gpio & TIOCM_DTR)
>> + mctrl |= UART_MCR_DTR;
>> + else
>> + mctrl &= ~UART_MCR_DTR;
>> + }
>> +
>> + return mctrl;
>> }
>
> These are using OR logic with potentially volatile data. Shouldn't we mask
> unused bits in UART_MCR in case of up->gpios != NULL?
Sorry, I don't see, which bits you are referring to? Could you please be
a bit more specific with the variable / macro meant (example)?
>> + if (up->gpios == 0)
>
> This is type inconsistency with this check as far as I understand.
> I guess you have to do either (up->gpios == NULL), or (!up->gpios).
Ah, right. Thanks for spotting.
Thanks,
Stefan
^ permalink raw reply
* Re: [PATCH 2/2 v5] tty/serial/8250: use mctrl_gpio helpers
From: Andy Shevchenko @ 2019-06-11 12:44 UTC (permalink / raw)
To: Stefan Roese
Cc: linux-serial, linux-kernel, Yegor Yefremov, Mika Westerberg,
Giulio Benetti, Greg Kroah-Hartman
In-Reply-To: <20190611105603.4435-2-sr@denx.de>
On Tue, Jun 11, 2019 at 12:56:03PM +0200, Stefan Roese wrote:
> From: Yegor Yefremov <yegorslists@googlemail.com>
>
> This patch permits the usage for GPIOs to control
> the CTS/RTS/DTR/DSR/DCD/RI signals.
> static inline void serial8250_out_MCR(struct uart_8250_port *up, int value)
> {
> serial_out(up, UART_MCR, value);
> +
> + if (up->gpios) {
> + int mctrl_gpio = 0;
> +
> + if (value & UART_MCR_RTS)
> + mctrl_gpio |= TIOCM_RTS;
> + if (value & UART_MCR_DTR)
> + mctrl_gpio |= TIOCM_DTR;
> +
> + mctrl_gpio_set(up->gpios, mctrl_gpio);
> + }
> }
>
> static inline int serial8250_in_MCR(struct uart_8250_port *up)
> {
> - return serial_in(up, UART_MCR);
> + int mctrl;
> +
> + mctrl = serial_in(up, UART_MCR);
> +
> + if (up->gpios) {
> + int mctrl_gpio = 0;
> +
> + /* save current MCR values */
> + if (mctrl & UART_MCR_RTS)
> + mctrl_gpio |= TIOCM_RTS;
> + if (mctrl & UART_MCR_DTR)
> + mctrl_gpio |= TIOCM_DTR;
> +
> + mctrl_gpio = mctrl_gpio_get_outputs(up->gpios, &mctrl_gpio);
> + if (mctrl_gpio & TIOCM_RTS)
> + mctrl |= UART_MCR_RTS;
> + else
> + mctrl &= ~UART_MCR_RTS;
> +
> + if (mctrl_gpio & TIOCM_DTR)
> + mctrl |= UART_MCR_DTR;
> + else
> + mctrl &= ~UART_MCR_DTR;
> + }
> +
> + return mctrl;
> }
These are using OR logic with potentially volatile data. Shouldn't we mask
unused bits in UART_MCR in case of up->gpios != NULL?
> + if (up->gpios == 0)
This is type inconsistency with this check as far as I understand.
I guess you have to do either (up->gpios == NULL), or (!up->gpios).
> ret = 0;
+ Blank line.
> + if (up->gpios)
> + return mctrl_gpio_get(up->gpios, &ret);
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* [PATCH v2 10/10] ARM: dts: stm32: add wakeup capability on each usart/uart on stm32mp157c
From: Erwan Le Ray @ 2019-06-11 12:25 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, Maxime Coquelin, Alexandre Torgue,
Rob Herring, Mark Rutland
Cc: linux-serial, linux-stm32, linux-arm-kernel, linux-kernel,
devicetree, Erwan Le Ray, Fabrice Gasnier
In-Reply-To: <1560255930-22554-1-git-send-email-erwan.leray@st.com>
- Mark all usart/uart devices as wakeup source.
- Identify all dedicated interrupts with a specific interrupt name (either
"event" or "wakeup").
- add interrupts-extended wakeup interrupt
Signed-off-by: Erwan Le Ray <erwan.leray@st.com>
diff --git a/arch/arm/boot/dts/stm32mp157c.dtsi b/arch/arm/boot/dts/stm32mp157c.dtsi
index 2afeee6..de5b1bf 100644
--- a/arch/arm/boot/dts/stm32mp157c.dtsi
+++ b/arch/arm/boot/dts/stm32mp157c.dtsi
@@ -395,32 +395,44 @@
usart2: serial@4000e000 {
compatible = "st,stm32h7-uart";
reg = <0x4000e000 0x400>;
- interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "event", "wakeup";
+ interrupts-extended = <&intc GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>,
+ <&exti 27 1>;
clocks = <&rcc USART2_K>;
+ wakeup-source;
status = "disabled";
};
usart3: serial@4000f000 {
compatible = "st,stm32h7-uart";
reg = <0x4000f000 0x400>;
- interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "event", "wakeup";
+ interrupts-extended = <&intc GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>,
+ <&exti 28 1>;
clocks = <&rcc USART3_K>;
+ wakeup-source;
status = "disabled";
};
uart4: serial@40010000 {
compatible = "st,stm32h7-uart";
reg = <0x40010000 0x400>;
- interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "event", "wakeup";
+ interrupts-extended = <&intc GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>,
+ <&exti 30 1>;
clocks = <&rcc UART4_K>;
+ wakeup-source;
status = "disabled";
};
uart5: serial@40011000 {
compatible = "st,stm32h7-uart";
reg = <0x40011000 0x400>;
- interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "event", "wakeup";
+ interrupts-extended = <&intc GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
+ <&exti 31 1>;
clocks = <&rcc UART5_K>;
+ wakeup-source;
status = "disabled";
};
@@ -512,16 +524,22 @@
uart7: serial@40018000 {
compatible = "st,stm32h7-uart";
reg = <0x40018000 0x400>;
- interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "event", "wakeup";
+ interrupts-extended = <&intc GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>,
+ <&exti 32 1>;
clocks = <&rcc UART7_K>;
+ wakeup-source;
status = "disabled";
};
uart8: serial@40019000 {
compatible = "st,stm32h7-uart";
reg = <0x40019000 0x400>;
- interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "event", "wakeup";
+ interrupts-extended = <&intc GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>,
+ <&exti 33 1>;
clocks = <&rcc UART8_K>;
+ wakeup-source;
status = "disabled";
};
@@ -588,8 +606,11 @@
usart6: serial@44003000 {
compatible = "st,stm32h7-uart";
reg = <0x44003000 0x400>;
- interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "event", "wakeup";
+ interrupts-extended = <&intc GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>,
+ <&exti 29 1>;
clocks = <&rcc USART6_K>;
+ wakeup-source;
status = "disabled";
};
@@ -1201,8 +1222,11 @@
usart1: serial@5c000000 {
compatible = "st,stm32h7-uart";
reg = <0x5c000000 0x400>;
- interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "event", "wakeup";
+ interrupts-extended = <&intc GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>,
+ <&exti 26 1>;
clocks = <&rcc USART1_K>;
+ wakeup-source;
status = "disabled";
};
--
1.9.1
^ permalink raw reply related
* [PATCH v2 09/10] ARM: dts: stm32: Update UART4 pin states on stm32mp157a-dk1
From: Erwan Le Ray @ 2019-06-11 12:25 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, Maxime Coquelin, Alexandre Torgue,
Rob Herring, Mark Rutland
Cc: linux-serial, linux-stm32, linux-arm-kernel, linux-kernel,
devicetree, Erwan Le Ray, Fabrice Gasnier, Bich Hemon
In-Reply-To: <1560255930-22554-1-git-send-email-erwan.leray@st.com>
From: Bich Hemon <bich.hemon@st.com>
Add idle and no_console_suspend states to uart4 pin configuration.
Signed-off-by: Bich Hemon <bich.hemon@st.com>
Signed-off-by: Erwan Le Ray <erwan.leray@st.com>
diff --git a/arch/arm/boot/dts/stm32mp157a-dk1.dts b/arch/arm/boot/dts/stm32mp157a-dk1.dts
index 098dbfb..b851f80 100644
--- a/arch/arm/boot/dts/stm32mp157a-dk1.dts
+++ b/arch/arm/boot/dts/stm32mp157a-dk1.dts
@@ -244,7 +244,10 @@
};
&uart4 {
- pinctrl-names = "default";
+ pinctrl-names = "default", "sleep", "idle", "no_console_suspend";
pinctrl-0 = <&uart4_pins_a>;
+ pinctrl-1 = <&uart4_sleep_pins_a>;
+ pinctrl-2 = <&uart4_idle_pins_a>;
+ pinctrl-3 = <&uart4_pins_a>;
status = "okay";
};
--
1.9.1
^ permalink raw reply related
* [PATCH v2 08/10] ARM: dts: stm32: Update pin states for uart4 on stm32mp157c-ed1
From: Erwan Le Ray @ 2019-06-11 12:25 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, Maxime Coquelin, Alexandre Torgue,
Rob Herring, Mark Rutland
Cc: linux-serial, linux-stm32, linux-arm-kernel, linux-kernel,
devicetree, Erwan Le Ray, Fabrice Gasnier, Bich Hemon
In-Reply-To: <1560255930-22554-1-git-send-email-erwan.leray@st.com>
From: Bich Hemon <bich.hemon@st.com>
Add idle and no_console_suspend states to uart4 pin configuration
Signed-off-by: Bich Hemon <bich.hemon@st.com>
Signed-off-by: Erwan Le Ray <erwan.leray@st.com>
diff --git a/arch/arm/boot/dts/stm32mp157c-ed1.dts b/arch/arm/boot/dts/stm32mp157c-ed1.dts
index 62a8c78..34cc847 100644
--- a/arch/arm/boot/dts/stm32mp157c-ed1.dts
+++ b/arch/arm/boot/dts/stm32mp157c-ed1.dts
@@ -251,8 +251,11 @@
};
&uart4 {
- pinctrl-names = "default";
+ pinctrl-names = "default", "sleep", "idle", "no_console_suspend";
pinctrl-0 = <&uart4_pins_a>;
+ pinctrl-1 = <&uart4_sleep_pins_a>;
+ pinctrl-2 = <&uart4_idle_pins_a>;
+ pinctrl-3 = <&uart4_pins_a>;
status = "okay";
};
--
1.9.1
^ permalink raw reply related
* [PATCH v2 07/10] ARM: dts: stm32: update uart4 pin configurations for low power
From: Erwan Le Ray @ 2019-06-11 12:25 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, Maxime Coquelin, Alexandre Torgue,
Rob Herring, Mark Rutland
Cc: linux-serial, linux-stm32, linux-arm-kernel, linux-kernel,
devicetree, Erwan Le Ray, Fabrice Gasnier, Bich Hemon
In-Reply-To: <1560255930-22554-1-git-send-email-erwan.leray@st.com>
Currently, pinctrl states defines only one "sleep" configuration for pins,
no matter the possible uart low power modes (Rx pin always kept active).
Sleep pin configuration is refined for low power modes:
- "sleep" (no wakeup & console suspend enabled): put pins in analog state
to optimize power
- "idle" (wakeup capability): keep Rx pin in alternate function
- "default" state remains untouched, to be used while the UART is active
or in case the no_console_suspend mode is enabled
Signed-off-by: Bich Hemon <bich.hemon@st.com>
Signed-off-by: Erwan Le Ray <erwan.leray@st.com>
diff --git a/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi b/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
index 85c417d..2e1ab1b 100644
--- a/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
+++ b/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
@@ -599,6 +599,23 @@
bias-disable;
};
};
+
+ uart4_idle_pins_a: uart4-idle-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('G', 11, ANALOG)>; /* UART4_TX */
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('B', 2, AF8)>; /* UART4_RX */
+ bias-disable;
+ };
+ };
+
+ uart4_sleep_pins_a: uart4-sleep-0 {
+ pins {
+ pinmux = <STM32_PINMUX('G', 11, ANALOG)>, /* UART4_TX */
+ <STM32_PINMUX('B', 2, ANALOG)>; /* UART4_RX */
+ };
+ };
};
pinctrl_z: pin-controller-z@54004000 {
--
1.9.1
^ permalink raw reply related
* [PATCH v2 06/10] serial: stm32: add support for no_console_suspend
From: Erwan Le Ray @ 2019-06-11 12:25 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, Maxime Coquelin, Alexandre Torgue,
Rob Herring, Mark Rutland
Cc: linux-serial, linux-stm32, linux-arm-kernel, linux-kernel,
devicetree, Erwan Le Ray, Fabrice Gasnier, Bich Hemon
In-Reply-To: <1560255930-22554-1-git-send-email-erwan.leray@st.com>
In order to display console messages in low power mode, console pins
must be kept active after suspend call.
Signed-off-by: Bich Hemon <bich.hemon@st.com>
Signed-off-by: Erwan Le Ray <erwan.leray@st.com>
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
index 0d43711..00e4d7a 100644
--- a/drivers/tty/serial/stm32-usart.c
+++ b/drivers/tty/serial/stm32-usart.c
@@ -24,6 +24,8 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/pinctrl/devinfo.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/pm_wakeirq.h>
@@ -846,6 +848,7 @@ static int stm32_init_port(struct stm32_port *stm32port,
{
struct uart_port *port = &stm32port->port;
struct resource *res;
+ struct pinctrl *uart_pinctrl;
int ret;
port->iotype = UPIO_MEM;
@@ -879,6 +882,24 @@ static int stm32_init_port(struct stm32_port *stm32port,
stm32port->fifoen = stm32port->info->cfg.has_fifo;
+ uart_pinctrl = devm_pinctrl_get(&pdev->dev);
+ if (IS_ERR(uart_pinctrl)) {
+ ret = PTR_ERR(uart_pinctrl);
+ if (ret != -ENODEV) {
+ dev_err(&pdev->dev, "Can't get pinctrl, error %d\n",
+ ret);
+ return ret;
+ }
+ stm32port->console_pins = ERR_PTR(-ENODEV);
+ } else {
+ stm32port->console_pins = pinctrl_lookup_state
+ (uart_pinctrl, "no_console_suspend");
+ }
+
+ if (IS_ERR(stm32port->console_pins) && PTR_ERR(stm32port->console_pins)
+ != -ENODEV)
+ return PTR_ERR(stm32port->console_pins);
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
port->membase = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(port->membase))
@@ -1303,6 +1324,7 @@ static void __maybe_unused stm32_serial_enable_wakeup(struct uart_port *port,
static int __maybe_unused stm32_serial_suspend(struct device *dev)
{
struct uart_port *port = dev_get_drvdata(dev);
+ struct stm32_port *stm32_port = to_stm32_port(port);
uart_suspend_port(&stm32_usart_driver, port);
@@ -1311,7 +1333,19 @@ static int __maybe_unused stm32_serial_suspend(struct device *dev)
else
stm32_serial_enable_wakeup(port, false);
- pinctrl_pm_select_sleep_state(dev);
+ if (uart_console(port) && !console_suspend_enabled) {
+ if (IS_ERR(stm32_port->console_pins)) {
+ dev_err(dev, "no_console_suspend pinctrl not found\n");
+ return PTR_ERR(stm32_port->console_pins);
+ }
+
+ pinctrl_select_state(dev->pins->p, stm32_port->console_pins);
+ } else {
+ if (device_may_wakeup(dev))
+ pinctrl_pm_select_idle_state(dev);
+ else
+ pinctrl_pm_select_sleep_state(dev);
+ }
return 0;
}
diff --git a/drivers/tty/serial/stm32-usart.h b/drivers/tty/serial/stm32-usart.h
index 30d2433..050fe04 100644
--- a/drivers/tty/serial/stm32-usart.h
+++ b/drivers/tty/serial/stm32-usart.h
@@ -255,6 +255,7 @@ struct stm32_port {
bool fifoen;
int wakeirq;
int rdr_mask; /* receive data register mask */
+ struct pinctrl_state *console_pins;
};
static struct stm32_port stm32_ports[STM32_MAX_PORTS];
--
1.9.1
^ permalink raw reply related
* [PATCH v2 05/10] serial: stm32: Use __maybe_unused instead of #if CONFIG_PM_SLEEP
From: Erwan Le Ray @ 2019-06-11 12:25 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, Maxime Coquelin, Alexandre Torgue,
Rob Herring, Mark Rutland
Cc: linux-serial, linux-stm32, linux-arm-kernel, linux-kernel,
devicetree, Erwan Le Ray, Fabrice Gasnier
In-Reply-To: <1560255930-22554-1-git-send-email-erwan.leray@st.com>
Use __maybe_unused for power management related functionsinstead of
fixes: 270e5a74fe4c ("serial: stm32: add wakeup mechanism")
Signed-off-by: Erwan Le Ray <erwan.leray@st.com>
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
index 60f3faf..0d43711 100644
--- a/drivers/tty/serial/stm32-usart.c
+++ b/drivers/tty/serial/stm32-usart.c
@@ -1275,8 +1275,8 @@ static int stm32_console_setup(struct console *co, char *options)
.cons = STM32_SERIAL_CONSOLE,
};
-#ifdef CONFIG_PM_SLEEP
-static void stm32_serial_enable_wakeup(struct uart_port *port, bool enable)
+static void __maybe_unused stm32_serial_enable_wakeup(struct uart_port *port,
+ bool enable)
{
struct stm32_port *stm32_port = to_stm32_port(port);
struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
@@ -1300,7 +1300,7 @@ static void stm32_serial_enable_wakeup(struct uart_port *port, bool enable)
}
}
-static int stm32_serial_suspend(struct device *dev)
+static int __maybe_unused stm32_serial_suspend(struct device *dev)
{
struct uart_port *port = dev_get_drvdata(dev);
@@ -1316,7 +1316,7 @@ static int stm32_serial_suspend(struct device *dev)
return 0;
}
-static int stm32_serial_resume(struct device *dev)
+static int __maybe_unused stm32_serial_resume(struct device *dev)
{
struct uart_port *port = dev_get_drvdata(dev);
@@ -1327,7 +1327,6 @@ static int stm32_serial_resume(struct device *dev)
return uart_resume_port(&stm32_usart_driver, port);
}
-#endif /* CONFIG_PM_SLEEP */
static int __maybe_unused stm32_serial_runtime_suspend(struct device *dev)
{
--
1.9.1
^ permalink raw reply related
* [PATCH v2 04/10] serial: stm32: add pm_runtime support
From: Erwan Le Ray @ 2019-06-11 12:25 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, Maxime Coquelin, Alexandre Torgue,
Rob Herring, Mark Rutland
Cc: linux-serial, linux-stm32, linux-arm-kernel, linux-kernel,
devicetree, Erwan Le Ray, Fabrice Gasnier, Bich Hemon
In-Reply-To: <1560255930-22554-1-git-send-email-erwan.leray@st.com>
Use pm_runtime for clock management.
Signed-off-by: Bich Hemon <bich.hemon@st.com>
Signed-off-by: Erwan Le Ray <erwan.leray@st.com>
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
index 04eda75..60f3faf 100644
--- a/drivers/tty/serial/stm32-usart.c
+++ b/drivers/tty/serial/stm32-usart.c
@@ -809,13 +809,13 @@ static void stm32_pm(struct uart_port *port, unsigned int state,
switch (state) {
case UART_PM_STATE_ON:
- clk_prepare_enable(stm32port->clk);
+ pm_runtime_get_sync(port->dev);
break;
case UART_PM_STATE_OFF:
spin_lock_irqsave(&port->lock, flags);
stm32_clr_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit));
spin_unlock_irqrestore(&port->lock, flags);
- clk_disable_unprepare(stm32port->clk);
+ pm_runtime_put_sync(port->dev);
break;
}
}
@@ -1110,6 +1110,11 @@ static int stm32_serial_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, &stm32port->port);
+ pm_runtime_get_noresume(&pdev->dev);
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_put_sync(&pdev->dev);
+
return 0;
err_wirq:
@@ -1131,6 +1136,9 @@ static int stm32_serial_remove(struct platform_device *pdev)
struct uart_port *port = platform_get_drvdata(pdev);
struct stm32_port *stm32_port = to_stm32_port(port);
struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
+ int err;
+
+ pm_runtime_get_sync(&pdev->dev);
stm32_clr_bits(port, ofs->cr3, USART_CR3_DMAR);
@@ -1159,7 +1167,12 @@ static int stm32_serial_remove(struct platform_device *pdev)
clk_disable_unprepare(stm32_port->clk);
- return uart_remove_one_port(&stm32_usart_driver, port);
+ err = uart_remove_one_port(&stm32_usart_driver, port);
+
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+
+ return err;
}
@@ -1316,7 +1329,29 @@ static int stm32_serial_resume(struct device *dev)
}
#endif /* CONFIG_PM_SLEEP */
+static int __maybe_unused stm32_serial_runtime_suspend(struct device *dev)
+{
+ struct uart_port *port = dev_get_drvdata(dev);
+ struct stm32_port *stm32port = container_of(port,
+ struct stm32_port, port);
+
+ clk_disable_unprepare(stm32port->clk);
+
+ return 0;
+}
+
+static int __maybe_unused stm32_serial_runtime_resume(struct device *dev)
+{
+ struct uart_port *port = dev_get_drvdata(dev);
+ struct stm32_port *stm32port = container_of(port,
+ struct stm32_port, port);
+
+ return clk_prepare_enable(stm32port->clk);
+}
+
static const struct dev_pm_ops stm32_serial_pm_ops = {
+ SET_RUNTIME_PM_OPS(stm32_serial_runtime_suspend,
+ stm32_serial_runtime_resume, NULL)
SET_SYSTEM_SLEEP_PM_OPS(stm32_serial_suspend, stm32_serial_resume)
};
--
1.9.1
^ permalink raw reply related
* [PATCH v2 03/10] serial: stm32: select pinctrl state in each suspend/resume function
From: Erwan Le Ray @ 2019-06-11 12:25 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, Maxime Coquelin, Alexandre Torgue,
Rob Herring, Mark Rutland
Cc: linux-serial, linux-stm32, linux-arm-kernel, linux-kernel,
devicetree, Erwan Le Ray, Fabrice Gasnier, Bich Hemon
In-Reply-To: <1560255930-22554-1-git-send-email-erwan.leray@st.com>
From: Bich Hemon <bich.hemon@st.com>
Select either pinctrl sleep state in suspend function or default state in
resume function.
Signed-off-by: Bich Hemon <bich.hemon@st.com>
Signed-off-by: Erwan Le Ray <erwan.leray@st.com>
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
index 9c2b04e..04eda75 100644
--- a/drivers/tty/serial/stm32-usart.c
+++ b/drivers/tty/serial/stm32-usart.c
@@ -1298,6 +1298,8 @@ static int stm32_serial_suspend(struct device *dev)
else
stm32_serial_enable_wakeup(port, false);
+ pinctrl_pm_select_sleep_state(dev);
+
return 0;
}
@@ -1305,6 +1307,8 @@ static int stm32_serial_resume(struct device *dev)
{
struct uart_port *port = dev_get_drvdata(dev);
+ pinctrl_pm_select_default_state(dev);
+
if (device_may_wakeup(dev))
stm32_serial_enable_wakeup(port, false);
--
1.9.1
^ permalink raw reply related
* [PATCH v2 02/10] dt-bindings: serial: add optional pinctrl states
From: Erwan Le Ray @ 2019-06-11 12:25 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, Maxime Coquelin, Alexandre Torgue,
Rob Herring, Mark Rutland
Cc: linux-serial, linux-stm32, linux-arm-kernel, linux-kernel,
devicetree, Erwan Le Ray, Fabrice Gasnier, Bich Hemon
In-Reply-To: <1560255930-22554-1-git-send-email-erwan.leray@st.com>
From: Bich Hemon <bich.hemon@st.com>
Add options for pinctrl states:
- "sleep" for low power
- "idle" for low power and wakeup capabilities enabled
- "no_console_suspend" for enabling console messages in low power
Signed-off-by: Bich Hemon <bich.hemon@st.com>
Signed-off-by: Erwan Le Ray <erwan.leray@st.com>
diff --git a/Documentation/devicetree/bindings/serial/st,stm32-usart.txt b/Documentation/devicetree/bindings/serial/st,stm32-usart.txt
index 5ec80c1..64a5ea9 100644
--- a/Documentation/devicetree/bindings/serial/st,stm32-usart.txt
+++ b/Documentation/devicetree/bindings/serial/st,stm32-usart.txt
@@ -13,7 +13,14 @@ Required properties:
- clocks: The input clock of the USART instance
Optional properties:
-- pinctrl: The reference on the pins configuration
+- pinctrl-names: Set to "default". An additional "sleep" state can be defined
+ to set pins in sleep state when in low power. In case the device is used as
+ a wakeup source, "idle" state is defined in order to keep RX pin active.
+ For a console device, an optional state "no_console_suspend" can be defined
+ to enable console messages during suspend. Typically, "no_console_suspend" and
+ "default" states can refer to the same pin configuration.
+- pinctrl-n: Phandle(s) pointing to pin configuration nodes.
+ For Pinctrl properties see ../pinctrl/pinctrl-bindings.txt
- st,hw-flow-ctrl: bool flag to enable hardware flow control.
- rs485-rts-delay, rs485-rx-during-tx, rs485-rts-active-low,
linux,rs485-enabled-at-boot-time: see rs485.txt.
@@ -31,8 +38,11 @@ usart4: serial@40004c00 {
reg = <0x40004c00 0x400>;
interrupts = <52>;
clocks = <&clk_pclk1>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "sleep", "idle", "no_console_suspend";
pinctrl-0 = <&pinctrl_usart4>;
+ pinctrl-1 = <&pinctrl_usart4_sleep>;
+ pinctrl-2 = <&pinctrl_usart4_idle>;
+ pinctrl-3 = <&pinctrl_usart4>;
};
usart2: serial@40004400 {
--
1.9.1
^ permalink raw reply related
* [PATCH v2 01/10] dt-bindings: serial: stm32: add wakeup option
From: Erwan Le Ray @ 2019-06-11 12:25 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, Maxime Coquelin, Alexandre Torgue,
Rob Herring, Mark Rutland
Cc: linux-serial, linux-stm32, linux-arm-kernel, linux-kernel,
devicetree, Erwan Le Ray, Fabrice Gasnier, Bich Hemon
In-Reply-To: <1560255930-22554-1-git-send-email-erwan.leray@st.com>
Add a note for enabling wakeup capabilities of usart
Signed-off-by: Bich Hemon <bich.hemon@st.com>
Signed-off-by: Erwan Le Ray <erwan.leray@st.com>
diff --git a/Documentation/devicetree/bindings/serial/st,stm32-usart.txt b/Documentation/devicetree/bindings/serial/st,stm32-usart.txt
index 9d3efed..5ec80c1 100644
--- a/Documentation/devicetree/bindings/serial/st,stm32-usart.txt
+++ b/Documentation/devicetree/bindings/serial/st,stm32-usart.txt
@@ -19,6 +19,11 @@ Optional properties:
linux,rs485-enabled-at-boot-time: see rs485.txt.
- dmas: phandle(s) to DMA controller node(s). Refer to stm32-dma.txt
- dma-names: "rx" and/or "tx"
+- wakeup-source: bool flag to indicate this device has wakeup capabilities
+- interrupt-names, if optional wake-up interrupt is used, should be:
+ - "event": the name for the interrupt line of the USART instance
+ - "wakeup" the name for the optional wake-up interrupt
+
Examples:
usart4: serial@40004c00 {
--
1.9.1
^ permalink raw reply related
* [PATCH v2 00/10] STM32 usart power improvements
From: Erwan Le Ray @ 2019-06-11 12:25 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, Maxime Coquelin, Alexandre Torgue,
Rob Herring, Mark Rutland
Cc: linux-serial, linux-stm32, linux-arm-kernel, linux-kernel,
devicetree, Erwan Le Ray, Fabrice Gasnier
This series delivers power improvements for stm32-usart driver.
Bich Hemon (4):
dt-bindings: serial: add optional pinctrl states
serial: stm32: select pinctrl state in each suspend/resume function
ARM: dts: stm32: Update pin states for uart4 on stm32mp157c-ed1
ARM: dts: stm32: Update UART4 pin states on stm32mp157a-dk1
Erwan Le Ray (6):
dt-bindings: serial: stm32: add wakeup option
serial: stm32: add pm_runtime support
serial: stm32: Use __maybe_unused instead of #if CONFIG_PM_SLEEP
serial: stm32: add support for no_console_suspend
ARM: dts: stm32: update uart4 pin configurations for low power
ARM: dts: stm32: add wakeup capability on each usart/uart on
stm32mp157c
.../devicetree/bindings/serial/st,stm32-usart.txt | 19 ++++-
arch/arm/boot/dts/stm32mp157-pinctrl.dtsi | 17 +++++
arch/arm/boot/dts/stm32mp157a-dk1.dts | 5 +-
arch/arm/boot/dts/stm32mp157c-ed1.dts | 5 +-
arch/arm/boot/dts/stm32mp157c.dtsi | 40 ++++++++--
drivers/tty/serial/stm32-usart.c | 88 ++++++++++++++++++++--
drivers/tty/serial/stm32-usart.h | 1 +
7 files changed, 155 insertions(+), 20 deletions(-)
--
1.9.1
^ permalink raw reply
* Re: [PATCH v3 1/2] dt-bindings: serial: add documentation for Rx in-band wakeup support
From: Claire Chang @ 2019-06-11 12:17 UTC (permalink / raw)
To: Greg KH
Cc: Mark Rutland, devicetree-u79uwXL29TY76Z2rM5mHXA, Nicolas Boichat,
changqi.hu-NuS5LvNUpcJWk0Htik3J/w, Rob Herring,
moderated list:ARM/Mediatek SoC support,
linux-serial-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20190611095752.GA24058-U8xfFu+wG4EAvxtiuMwx3w@public.gmane.org>
resent here: https://patchwork.ozlabs.org/patch/1113768/
sorry for the inconvenience
^ permalink raw reply
* [PATCH] dt-bindings: serial: add documentation for Rx in-band wakeup support
From: Claire Chang @ 2019-06-11 12:15 UTC (permalink / raw)
To: robh+dt-DgEjT+Ai2ygdnm+yROfE0A
Cc: mark.rutland-5wv7dgnIgG8, devicetree-u79uwXL29TY76Z2rM5mHXA,
drinkcat-F7+t8E8rja9g9hUCZPvPmw,
changqi.hu-NuS5LvNUpcJWk0Htik3J/w,
gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-serial-u79uwXL29TY76Z2rM5mHXA, Claire Chang
To support Rx in-band wakeup, one must create an interrupt specifier with
edge sensitivity on Rx pin and an addtional pinctrl to reconfigure Rx pin
to normal GPIO in sleep state. Driver will switch to sleep mode pinctrl and
enable irq wake before suspend and restore to default settings when
resuming.
Signed-off-by: Claire Chang <tientzu-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
---
Resending this patch since I forgot to cc device tree maintainers/mailing list.
The 2/2 patch in this series[1] is already in tty-next[2].
[1] https://patchwork.kernel.org/patch/10962299/
[2] https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git/log/?h=tty-testing
.../devicetree/bindings/serial/mtk-uart.txt | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/serial/mtk-uart.txt b/Documentation/devicetree/bindings/serial/mtk-uart.txt
index bcfb13194f16..3488b6e24e0c 100644
--- a/Documentation/devicetree/bindings/serial/mtk-uart.txt
+++ b/Documentation/devicetree/bindings/serial/mtk-uart.txt
@@ -21,7 +21,12 @@ Required properties:
- reg: The base address of the UART register bank.
-- interrupts: A single interrupt specifier.
+- interrupts or interrupts-extended:
+ index 0: an interrupt specifier for the UART controller itself
+ index 1: optional, an interrupt specifier with edge sensitivity on Rx pin to
+ support Rx in-band wake up. If one would like to use this feature,
+ one must create an addtional pinctrl to reconfigure Rx pin to normal
+ GPIO before suspend.
- clocks : Must contain an entry for each entry in clock-names.
See ../clocks/clock-bindings.txt for details.
@@ -37,7 +42,11 @@ Example:
uart0: serial@11006000 {
compatible = "mediatek,mt6589-uart", "mediatek,mt6577-uart";
reg = <0x11006000 0x400>;
- interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_LOW>;
+ interrupts-extended = <&sysirq GIC_SPI 51 IRQ_TYPE_LEVEL_LOW>,
+ <&gpio 121 IRQ_TYPE_EDGE_FALLING>;
clocks = <&uart_clk>, <&bus_clk>;
clock-names = "baud", "bus";
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&uart_pin>;
+ pinctrl-1 = <&uart_pin_sleep>;
};
--
2.22.0.rc2.383.gf4fbbf30c2-goog
^ permalink raw reply related
* [PATCH 2/2 v5] tty/serial/8250: use mctrl_gpio helpers
From: Stefan Roese @ 2019-06-11 10:56 UTC (permalink / raw)
To: linux-serial
Cc: linux-kernel, Yegor Yefremov, Mika Westerberg, Andy Shevchenko,
Giulio Benetti, Greg Kroah-Hartman
In-Reply-To: <20190611105603.4435-1-sr@denx.de>
From: Yegor Yefremov <yegorslists@googlemail.com>
This patch permits the usage for GPIOs to control
the CTS/RTS/DTR/DSR/DCD/RI signals.
Changed by Stefan:
Only call mctrl_gpio_init(), if the device has no ACPI companion device
to not break existing ACPI based systems. Also only use the mctrl_gpio_
functions when "gpios" is available.
Signed-off-by: Yegor Yefremov <yegorslists@googlemail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Stefan Roese <sr@denx.de>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Cc: Mika Westerberg <mika.westerberg@linux.intel.com>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Giulio Benetti <giulio.benetti@micronovasrl.com>
Cc: Yegor Yefremov <yegorslists@googlemail.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
v5:
- Dropped a few "if (up->gpios)" checks, as the mctrl_gpio_foo() API
handles gpios == NULL (return)
- 8250_omap: Changed "IS_ERR_OR_NULL(mctrl_gpio_to_gpiod(up->gpios, ...))"
to "up->gpios == NULL", as mctrl_gpio_to_gpiod() does not handle
gpios == NULL correctly.
v4:
- Added Mika's reviewed by tag
- Added Johan to Cc
v3:
- Only call mctrl_gpio_init(), if the device has no ACPI companion device
to not break existing ACPI based systems, as suggested by Andy
v2:
- No change
Please note that this patch was already applied before [1]. And later
reverted [2] because it introduced problems on some x86 based boards
(ACPI GPIO related). Here a detailed description of the issue at that
time:
https://lkml.org/lkml/2016/8/9/357
http://www.spinics.net/lists/linux-serial/msg23071.html
This is a re-send of the original patch that was applied at that time.
With patch 1/2 from this series this issue should be fixed now (please
note that I can't test it on such an x86 platform causing these
problems).
Andy (or Mika), perhaps it would be possible for you to test this
patch again, now with patch 1/2 of this series applied as well?
That would be really helpful.
Thanks,
Stefan
[1] 4ef03d328769 ("tty/serial/8250: use mctrl_gpio helpers")
[2] 5db4f7f80d16 ("Revert "tty/serial/8250: use mctrl_gpio helpers"")
.../devicetree/bindings/serial/8250.txt | 19 +++++++++
drivers/tty/serial/8250/8250.h | 40 ++++++++++++++++++-
drivers/tty/serial/8250/8250_core.c | 17 ++++++++
drivers/tty/serial/8250/8250_omap.c | 29 ++++++++------
drivers/tty/serial/8250/8250_port.c | 7 ++++
drivers/tty/serial/8250/Kconfig | 1 +
include/linux/serial_8250.h | 1 +
7 files changed, 100 insertions(+), 14 deletions(-)
diff --git a/Documentation/devicetree/bindings/serial/8250.txt b/Documentation/devicetree/bindings/serial/8250.txt
index 3cba12f855b7..20d351f268ef 100644
--- a/Documentation/devicetree/bindings/serial/8250.txt
+++ b/Documentation/devicetree/bindings/serial/8250.txt
@@ -53,6 +53,9 @@ Optional properties:
programmable TX FIFO thresholds.
- resets : phandle + reset specifier pairs
- overrun-throttle-ms : how long to pause uart rx when input overrun is encountered.
+- {rts,cts,dtr,dsr,rng,dcd}-gpios: specify a GPIO for RTS/CTS/DTR/DSR/RI/DCD
+ line respectively. It will use specified GPIO instead of the peripheral
+ function pin for the UART feature. If unsure, don't specify this property.
Note:
* fsl,ns16550:
@@ -74,3 +77,19 @@ Example:
interrupts = <10>;
reg-shift = <2>;
};
+
+Example for OMAP UART using GPIO-based modem control signals:
+
+ uart4: serial@49042000 {
+ compatible = "ti,omap3-uart";
+ reg = <0x49042000 0x400>;
+ interrupts = <80>;
+ ti,hwmods = "uart4";
+ clock-frequency = <48000000>;
+ cts-gpios = <&gpio3 5 GPIO_ACTIVE_LOW>;
+ rts-gpios = <&gpio3 6 GPIO_ACTIVE_LOW>;
+ dtr-gpios = <&gpio1 12 GPIO_ACTIVE_LOW>;
+ dsr-gpios = <&gpio1 13 GPIO_ACTIVE_LOW>;
+ dcd-gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
+ rng-gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
+ };
diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
index ebfb0bd5bef5..441aab94264b 100644
--- a/drivers/tty/serial/8250/8250.h
+++ b/drivers/tty/serial/8250/8250.h
@@ -11,6 +11,8 @@
#include <linux/serial_reg.h>
#include <linux/dmaengine.h>
+#include "../serial_mctrl_gpio.h"
+
struct uart_8250_dma {
int (*tx_dma)(struct uart_8250_port *p);
int (*rx_dma)(struct uart_8250_port *p);
@@ -142,11 +144,47 @@ void serial8250_em485_destroy(struct uart_8250_port *p);
static inline void serial8250_out_MCR(struct uart_8250_port *up, int value)
{
serial_out(up, UART_MCR, value);
+
+ if (up->gpios) {
+ int mctrl_gpio = 0;
+
+ if (value & UART_MCR_RTS)
+ mctrl_gpio |= TIOCM_RTS;
+ if (value & UART_MCR_DTR)
+ mctrl_gpio |= TIOCM_DTR;
+
+ mctrl_gpio_set(up->gpios, mctrl_gpio);
+ }
}
static inline int serial8250_in_MCR(struct uart_8250_port *up)
{
- return serial_in(up, UART_MCR);
+ int mctrl;
+
+ mctrl = serial_in(up, UART_MCR);
+
+ if (up->gpios) {
+ int mctrl_gpio = 0;
+
+ /* save current MCR values */
+ if (mctrl & UART_MCR_RTS)
+ mctrl_gpio |= TIOCM_RTS;
+ if (mctrl & UART_MCR_DTR)
+ mctrl_gpio |= TIOCM_DTR;
+
+ mctrl_gpio = mctrl_gpio_get_outputs(up->gpios, &mctrl_gpio);
+ if (mctrl_gpio & TIOCM_RTS)
+ mctrl |= UART_MCR_RTS;
+ else
+ mctrl &= ~UART_MCR_RTS;
+
+ if (mctrl_gpio & TIOCM_DTR)
+ mctrl |= UART_MCR_DTR;
+ else
+ mctrl &= ~UART_MCR_DTR;
+ }
+
+ return mctrl;
}
#if defined(__alpha__) && !defined(CONFIG_PCI)
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index e441221e04b9..a4470771005f 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -14,6 +14,7 @@
* serial8250_register_8250_port() ports
*/
+#include <linux/acpi.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/ioport.h>
@@ -982,6 +983,8 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
uart = serial8250_find_match_or_unused(&up->port);
if (uart && uart->port.type != PORT_8250_CIR) {
+ struct mctrl_gpios *gpios;
+
if (uart->port.dev)
uart_remove_one_port(&serial8250_reg, &uart->port);
@@ -1016,6 +1019,20 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
if (up->port.flags & UPF_FIXED_TYPE)
uart->port.type = up->port.type;
+ /*
+ * Only call mctrl_gpio_init(), if the device has no ACPI
+ * companion device
+ */
+ if (!has_acpi_companion(uart->port.dev)) {
+ gpios = mctrl_gpio_init(&uart->port, 0);
+ if (IS_ERR(gpios)) {
+ if (PTR_ERR(gpios) != -ENOSYS)
+ return PTR_ERR(gpios);
+ } else {
+ uart->gpios = gpios;
+ }
+ }
+
serial8250_set_defaults(uart);
/* Possibly override default I/O functions. */
diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
index 0a8316632d75..620330599d39 100644
--- a/drivers/tty/serial/8250/8250_omap.c
+++ b/drivers/tty/serial/8250/8250_omap.c
@@ -141,18 +141,20 @@ static void omap8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
serial8250_do_set_mctrl(port, mctrl);
- /*
- * Turn off autoRTS if RTS is lowered and restore autoRTS setting
- * if RTS is raised
- */
- lcr = serial_in(up, UART_LCR);
- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
- if ((mctrl & TIOCM_RTS) && (port->status & UPSTAT_AUTORTS))
- priv->efr |= UART_EFR_RTS;
- else
- priv->efr &= ~UART_EFR_RTS;
- serial_out(up, UART_EFR, priv->efr);
- serial_out(up, UART_LCR, lcr);
+ if (up->gpios == 0) {
+ /*
+ * Turn off autoRTS if RTS is lowered and restore autoRTS
+ * setting if RTS is raised
+ */
+ lcr = serial_in(up, UART_LCR);
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+ if ((mctrl & TIOCM_RTS) && (port->status & UPSTAT_AUTORTS))
+ priv->efr |= UART_EFR_RTS;
+ else
+ priv->efr &= ~UART_EFR_RTS;
+ serial_out(up, UART_EFR, priv->efr);
+ serial_out(up, UART_LCR, lcr);
+ }
}
/*
@@ -453,7 +455,8 @@ static void omap_8250_set_termios(struct uart_port *port,
priv->efr = 0;
up->port.status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS | UPSTAT_AUTOXOFF);
- if (termios->c_cflag & CRTSCTS && up->port.flags & UPF_HARD_FLOW) {
+ if (termios->c_cflag & CRTSCTS && up->port.flags & UPF_HARD_FLOW &&
+ up->gpios == 0) {
/* Enable AUTOCTS (autoRTS is enabled when RTS is raised) */
up->port.status |= UPSTAT_AUTOCTS | UPSTAT_AUTORTS;
priv->efr |= UART_EFR_CTS;
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index 2304a84eee3b..b86a16e2c9b6 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -1662,6 +1662,8 @@ static void serial8250_disable_ms(struct uart_port *port)
if (up->bugs & UART_BUG_NOMSR)
return;
+ mctrl_gpio_disable_ms(up->gpios);
+
up->ier &= ~UART_IER_MSI;
serial_port_out(port, UART_IER, up->ier);
}
@@ -1674,6 +1676,8 @@ static void serial8250_enable_ms(struct uart_port *port)
if (up->bugs & UART_BUG_NOMSR)
return;
+ mctrl_gpio_enable_ms(up->gpios);
+
up->ier |= UART_IER_MSI;
serial8250_rpm_get(up);
@@ -1951,6 +1955,9 @@ unsigned int serial8250_do_get_mctrl(struct uart_port *port)
serial8250_rpm_put(up);
ret = 0;
+ if (up->gpios)
+ return mctrl_gpio_get(up->gpios, &ret);
+
if (status & UART_MSR_DCD)
ret |= TIOCM_CAR;
if (status & UART_MSR_RI)
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 296115f6a4d8..509f6a3bb9ff 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -8,6 +8,7 @@ config SERIAL_8250
tristate "8250/16550 and compatible serial support"
depends on !S390
select SERIAL_CORE
+ select SERIAL_MCTRL_GPIO if GPIOLIB
---help---
This selects whether you want to include the driver for the standard
serial ports. The standard answer is Y. People who might say N
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index 5e0b59422a68..bb2bc99388ca 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -110,6 +110,7 @@ struct uart_8250_port {
* if no_console_suspend
*/
unsigned char probe;
+ struct mctrl_gpios *gpios;
#define UART_PROBE_RSA (1 << 0)
/*
--
2.22.0
^ permalink raw reply related
* [PATCH 1/2 v5] serial: mctrl_gpio: Check if GPIO property exisits before requesting it
From: Stefan Roese @ 2019-06-11 10:56 UTC (permalink / raw)
To: linux-serial
Cc: linux-kernel, Mika Westerberg, Andy Shevchenko, Yegor Yefremov,
Greg Kroah-Hartman, Giulio Benetti
This patch adds a check for the GPIOs property existence, before the
GPIO is requested. This fixes an issue seen when the 8250 mctrl_gpio
support is added (2nd patch in this patch series) on x86 platforms using
ACPI.
Here Mika's comments from 2016-08-09:
"
I noticed that with v4.8-rc1 serial console of some of our Broxton
systems does not work properly anymore. I'm able to see output but input
does not work.
I bisected it down to commit 4ef03d328769eddbfeca1f1c958fdb181a69c341
("tty/serial/8250: use mctrl_gpio helpers").
The reason why it fails is that in ACPI we do not have names for GPIOs
(except when _DSD is used) so we use the "idx" to index into _CRS GPIO
resources. Now mctrl_gpio_init_noauto() goes through a list of GPIOs
calling devm_gpiod_get_index_optional() passing "idx" of 0 for each. The
UART device in Broxton has following (simplified) ACPI description:
Device (URT4)
{
...
Name (_CRS, ResourceTemplate () {
GpioIo (Exclusive, PullDefault, 0x0000, 0x0000, IoRestrictionOutputOnly,
"\\_SB.GPO0", 0x00, ResourceConsumer)
{
0x003A
}
GpioIo (Exclusive, PullDefault, 0x0000, 0x0000, IoRestrictionOutputOnly,
"\\_SB.GPO0", 0x00, ResourceConsumer)
{
0x003D
}
})
In this case it finds the first GPIO (0x003A which happens to be RX pin
for that UART), turns it into GPIO which then breaks input for the UART
device. This also breaks systems with bluetooth connected to UART (those
typically have some GPIOs in their _CRS).
Any ideas how to fix this?
We cannot just drop the _CRS index lookup fallback because that would
break many existing machines out there so maybe we can limit this to
only DT enabled machines. Or alternatively probe if the property first
exists before trying to acquire the GPIOs (using
device_property_present()).
"
This patch implements the fix suggested by Mika in his statement above.
Signed-off-by: Stefan Roese <sr@denx.de>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Cc: Mika Westerberg <mika.westerberg@linux.intel.com>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Yegor Yefremov <yegorslists@googlemail.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Giulio Benetti <giulio.benetti@micronovasrl.com>
---
v5:
- Simplified the code a bit (Andy)
- Added gpio_str == NULL handling (Andy)
v4:
- Add missing free() calls (Johan)
- Added Mika's reviewed by tag
- Added Johan to Cc
v3:
- No change
v2:
- Include the problem description and analysis from Mika into the commit
text, as suggested by Greg.
drivers/tty/serial/serial_mctrl_gpio.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/tty/serial/serial_mctrl_gpio.c b/drivers/tty/serial/serial_mctrl_gpio.c
index 39ed56214cd3..65348887a749 100644
--- a/drivers/tty/serial/serial_mctrl_gpio.c
+++ b/drivers/tty/serial/serial_mctrl_gpio.c
@@ -116,6 +116,19 @@ struct mctrl_gpios *mctrl_gpio_init_noauto(struct device *dev, unsigned int idx)
for (i = 0; i < UART_GPIO_MAX; i++) {
enum gpiod_flags flags;
+ char *gpio_str;
+ bool present;
+
+ /* Check if GPIO property exists and continue if not */
+ gpio_str = kasprintf(GFP_KERNEL, "%s-gpios",
+ mctrl_gpios_desc[i].name);
+ if (!gpio_str)
+ continue;
+
+ present = device_property_present(dev, gpio_str);
+ kfree(gpio_str);
+ if (!present)
+ continue;
if (mctrl_gpios_desc[i].dir_out)
flags = GPIOD_OUT_LOW;
--
2.22.0
^ permalink raw reply related
* Re: [RFC v2 01/11] OPP: Don't overwrite rounded clk rate
From: Viresh Kumar @ 2019-06-11 10:54 UTC (permalink / raw)
To: swboyd, Rajendra Nayak
Cc: linux-kernel, linux-arm-msm, linux-pm, linux-serial, linux-spi,
dri-devel, linux-scsi, ulf.hansson, dianders, rafael
In-Reply-To: <20190320094918.20234-2-rnayak@codeaurora.org>
On 20-03-19, 15:19, Rajendra Nayak wrote:
> From: Stephen Boyd <swboyd@chromium.org>
>
> Doing this allows us to call this API with any rate requested and have
> it not need to match in the OPP table. Instead, we'll round the rate up
> to the nearest OPP that we see so that we can get the voltage or level
> that's required for that OPP. This supports users of OPP that want to
> specify the 'fmax' tables of a device instead of every single frequency
> that they need. And for devices that required the exact frequency, we
> can rely on the clk framework to round the rate to the nearest supported
> frequency instead of the OPP framework to do so.
>
> Note that this may affect drivers that don't want the clk framework to
> do rounding, but instead want the OPP table to do the rounding for them.
> Do we have that case? Should we add some flag to the OPP table to
> indicate this and then not have that flag set when there isn't an OPP
> table for the device and also introduce a property like 'opp-use-clk' to
> tell the table that it should use the clk APIs to round rates instead of
> OPP?
>
> Signed-off-by: Stephen Boyd <swboyd@chromium.org>
> Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
> ---
> drivers/opp/core.c | 8 +++++---
> 1 file changed, 5 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/opp/core.c b/drivers/opp/core.c
> index 0420f7e8ad5b..bc9a7762dd4c 100644
> --- a/drivers/opp/core.c
> +++ b/drivers/opp/core.c
> @@ -703,7 +703,7 @@ static int _set_required_opps(struct device *dev,
> int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
> {
> struct opp_table *opp_table;
> - unsigned long freq, old_freq;
> + unsigned long freq, opp_freq, old_freq, old_opp_freq;
> struct dev_pm_opp *old_opp, *opp;
> struct clk *clk;
> int ret;
> @@ -742,13 +742,15 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
> goto put_opp_table;
> }
>
> - old_opp = _find_freq_ceil(opp_table, &old_freq);
> + old_opp_freq = old_freq;
> + old_opp = _find_freq_ceil(opp_table, &old_opp_freq);
> if (IS_ERR(old_opp)) {
> dev_err(dev, "%s: failed to find current OPP for freq %lu (%ld)\n",
> __func__, old_freq, PTR_ERR(old_opp));
> }
>
> - opp = _find_freq_ceil(opp_table, &freq);
> + opp_freq = freq;
> + opp = _find_freq_ceil(opp_table, &opp_freq);
> if (IS_ERR(opp)) {
> ret = PTR_ERR(opp);
> dev_err(dev, "%s: failed to find OPP for freq %lu (%d)\n",
I see a logical problem with this patch.
Suppose the clock driver supports following frequencies: 500M, 800M,
1G, 1.2G and the OPP table contains following list: 500M, 1G, 1.2G
(i.e. missing 800M).
Now 800M should never get programmed as it isn't part of the OPP
table. But if you pass 600M to opp-set-rate, then it will end up
selecting 800M as clock driver will round up to the closest value.
Even if no one is doing this right now, it is a sensible usecase,
specially during testing of patches and I don't think we should avoid
it.
What exactly is the use case for which we need this patch ? What kind
of driver ? Some detail can be helpful to find another solution that
fixes this problem.
--
viresh
^ permalink raw reply
* Re: [PATCH v3 1/2] dt-bindings: serial: add documentation for Rx in-band wakeup support
From: Greg KH @ 2019-06-11 9:57 UTC (permalink / raw)
To: Claire Chang
Cc: Mark Rutland, devicetree-u79uwXL29TY76Z2rM5mHXA, Nicolas Boichat,
changqi.hu-NuS5LvNUpcJWk0Htik3J/w, Rob Herring,
moderated list:ARM/Mediatek SoC support,
linux-serial-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <CALiNf2_Kuu9agO31Wg2X4uUa0EHWYL=qG5RLQ=catn8M9XDKGQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
On Tue, Jun 11, 2019 at 05:53:54PM +0800, Claire Chang wrote:
> (cc-ed device tree maintainers and mailing list)
>
> The second patch in this series[1] is already in tty-next[2].
>
> Sorry for not cc-ing device tree maintainers/mailing list at the beginning.
> I can resend this patch if needed.
Please do, as it is not here for them to review :(
greg k-h
^ permalink raw reply
* Re: [PATCH v3 1/2] dt-bindings: serial: add documentation for Rx in-band wakeup support
From: Claire Chang @ 2019-06-11 9:53 UTC (permalink / raw)
To: gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r
Cc: Mark Rutland, devicetree-u79uwXL29TY76Z2rM5mHXA, Nicolas Boichat,
changqi.hu-NuS5LvNUpcJWk0Htik3J/w, Rob Herring,
moderated list:ARM/Mediatek SoC support,
linux-serial-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20190527083150.220194-2-tientzu-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
(cc-ed device tree maintainers and mailing list)
The second patch in this series[1] is already in tty-next[2].
Sorry for not cc-ing device tree maintainers/mailing list at the beginning.
I can resend this patch if needed.
Thanks.
[1] https://patchwork.kernel.org/patch/10962299/
[2] https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git/log/?h=tty-testing
^ permalink raw reply
* Re: [PATCH v3] tty: serial: msm_serial: avoid system lockup condition
From: Rob Clark @ 2019-06-10 19:39 UTC (permalink / raw)
To: Jorge Ramirez
Cc: Greg KH, agross, David Brown, jslaby, linux-arm-msm, linux-serial,
Linux Kernel Mailing List, khasim.mohammed, Bjorn Andersson
In-Reply-To: <e656ddd3-f327-818d-3688-f24fddcb52c5@linaro.org>
On Mon, Jun 10, 2019 at 12:11 PM Jorge Ramirez
<jorge.ramirez-ortiz@linaro.org> wrote:
>
> On 6/10/19 19:53, Rob Clark wrote:
> > On Mon, Jun 10, 2019 at 10:23 AM Jorge Ramirez-Ortiz
> > <jorge.ramirez-ortiz@linaro.org> wrote:
> >> The function msm_wait_for_xmitr can be taken with interrupts
> >> disabled. In order to avoid a potential system lockup - demonstrated
> >> under stress testing conditions on SoC QCS404/5 - make sure we wait
> >> for a bounded amount of time.
> >>
> >> Tested on SoC QCS404.
> >>
> >> Signed-off-by: Jorge Ramirez-Ortiz <jorge.ramirez-ortiz@linaro.org>
> >
> > I had observed that heavy UART traffic would lockup the system (on
> > sdm845, but I guess same serial driver)?
> >
> > But a comment from the peanut gallary: wouldn't this fix lead to TX
> > corruption, ie. writing more into TX fifo before hw is ready? I
> > haven't looked closely at the driver, but a way to wait without irqs
> > disabled would seem nicer..
> >
> > BR,
> > -R
> >
>
> I think sdm845 uses a different driver (qcom_geni_serial.c) but yes in
> any case we need to determine the sequence leading to the lockup. In our
> internal releases we are adding additional debug information to try to
> capture this info.
ahh, ok.. perhaps qcom_geni_serial has a similar issue.. fwiw where I
tend to hit it is debugging mesa, bugs that can trigger GPU lockups
can tricker a lot of them, and a lot of dmesg spew. Which in turn
seems to freeze usb (? I think.. I'm using a usb-c ethernet adapter)
making it hard to ctrl-c the thing that is causing the GPU lockups in
the first place.
> But also I dont think this means that the safety net should not be used
yeah, probably not worse than the current state.. although a proper
solution would be nice
> btw, do you think that perhaps we should add a WARN_ONCE() on timeout?.
not sure if backtrace adds much value here.. but perhaps a (very)
ratelimited warning msg? You don't want to make the underlying
problem too much worse with too much debug msg but some hint about
what is happening could be useful.
BR,
-R
^ permalink raw reply
* Re: [PATCH v3] tty: serial: msm_serial: avoid system lockup condition
From: Jorge Ramirez @ 2019-06-10 19:11 UTC (permalink / raw)
To: Rob Clark
Cc: Greg KH, agross, David Brown, jslaby, linux-arm-msm, linux-serial,
Linux Kernel Mailing List, khasim.mohammed, Bjorn Andersson
In-Reply-To: <CAF6AEGuAPurGcRh42iRkt3paD=kWLJw-ic_LL1QGY=ws8_00XA@mail.gmail.com>
On 6/10/19 19:53, Rob Clark wrote:
> On Mon, Jun 10, 2019 at 10:23 AM Jorge Ramirez-Ortiz
> <jorge.ramirez-ortiz@linaro.org> wrote:
>> The function msm_wait_for_xmitr can be taken with interrupts
>> disabled. In order to avoid a potential system lockup - demonstrated
>> under stress testing conditions on SoC QCS404/5 - make sure we wait
>> for a bounded amount of time.
>>
>> Tested on SoC QCS404.
>>
>> Signed-off-by: Jorge Ramirez-Ortiz <jorge.ramirez-ortiz@linaro.org>
>
> I had observed that heavy UART traffic would lockup the system (on
> sdm845, but I guess same serial driver)?
>
> But a comment from the peanut gallary: wouldn't this fix lead to TX
> corruption, ie. writing more into TX fifo before hw is ready? I
> haven't looked closely at the driver, but a way to wait without irqs
> disabled would seem nicer..
>
> BR,
> -R
>
I think sdm845 uses a different driver (qcom_geni_serial.c) but yes in
any case we need to determine the sequence leading to the lockup. In our
internal releases we are adding additional debug information to try to
capture this info.
But also I dont think this means that the safety net should not be used
btw, do you think that perhaps we should add a WARN_ONCE() on timeout?.
^ permalink raw reply
* Re: [PATCH v3] tty: serial: msm_serial: avoid system lockup condition
From: Rob Clark @ 2019-06-10 17:53 UTC (permalink / raw)
To: Jorge Ramirez-Ortiz
Cc: Greg KH, agross, David Brown, jslaby, linux-arm-msm, linux-serial,
Linux Kernel Mailing List, khasim.mohammed, Bjorn Andersson
In-Reply-To: <20190610172308.21129-1-jorge.ramirez-ortiz@linaro.org>
On Mon, Jun 10, 2019 at 10:23 AM Jorge Ramirez-Ortiz
<jorge.ramirez-ortiz@linaro.org> wrote:
>
> The function msm_wait_for_xmitr can be taken with interrupts
> disabled. In order to avoid a potential system lockup - demonstrated
> under stress testing conditions on SoC QCS404/5 - make sure we wait
> for a bounded amount of time.
>
> Tested on SoC QCS404.
>
> Signed-off-by: Jorge Ramirez-Ortiz <jorge.ramirez-ortiz@linaro.org>
I had observed that heavy UART traffic would lockup the system (on
sdm845, but I guess same serial driver)?
But a comment from the peanut gallary: wouldn't this fix lead to TX
corruption, ie. writing more into TX fifo before hw is ready? I
haven't looked closely at the driver, but a way to wait without irqs
disabled would seem nicer..
BR,
-R
> ---
> v2: fix exit condition (timeout --> !timeout)
> v3: add these clarification messages
>
> drivers/tty/serial/msm_serial.c | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
> index 23833ad952ba..3657a24913fc 100644
> --- a/drivers/tty/serial/msm_serial.c
> +++ b/drivers/tty/serial/msm_serial.c
> @@ -383,10 +383,14 @@ static void msm_request_rx_dma(struct msm_port *msm_port, resource_size_t base)
>
> static inline void msm_wait_for_xmitr(struct uart_port *port)
> {
> + unsigned int timeout = 500000;
> +
> while (!(msm_read(port, UART_SR) & UART_SR_TX_EMPTY)) {
> if (msm_read(port, UART_ISR) & UART_ISR_TX_READY)
> break;
> udelay(1);
> + if (!timeout--)
> + break;
> }
> msm_write(port, UART_CR_CMD_RESET_TX_READY, UART_CR);
> }
> --
> 2.21.0
>
^ permalink raw reply
* [PATCH v3] tty: serial: msm_serial: avoid system lockup condition
From: Jorge Ramirez-Ortiz @ 2019-06-10 17:23 UTC (permalink / raw)
To: jorge.ramirez-ortiz, gregkh, agross, david.brown, jslaby
Cc: linux-arm-msm, linux-serial, linux-kernel, khasim.mohammed,
bjorn.andersson
The function msm_wait_for_xmitr can be taken with interrupts
disabled. In order to avoid a potential system lockup - demonstrated
under stress testing conditions on SoC QCS404/5 - make sure we wait
for a bounded amount of time.
Tested on SoC QCS404.
Signed-off-by: Jorge Ramirez-Ortiz <jorge.ramirez-ortiz@linaro.org>
---
v2: fix exit condition (timeout --> !timeout)
v3: add these clarification messages
drivers/tty/serial/msm_serial.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index 23833ad952ba..3657a24913fc 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -383,10 +383,14 @@ static void msm_request_rx_dma(struct msm_port *msm_port, resource_size_t base)
static inline void msm_wait_for_xmitr(struct uart_port *port)
{
+ unsigned int timeout = 500000;
+
while (!(msm_read(port, UART_SR) & UART_SR_TX_EMPTY)) {
if (msm_read(port, UART_ISR) & UART_ISR_TX_READY)
break;
udelay(1);
+ if (!timeout--)
+ break;
}
msm_write(port, UART_CR_CMD_RESET_TX_READY, UART_CR);
}
--
2.21.0
^ 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