* [PATCH 2/2 v3] serial: bfin-uart: Remove ASYNC_CTS_FLOW flag for hardware automatic CTS.
From: Sonic Zhang @ 2011-12-13 4:22 UTC (permalink / raw)
To: Greg Kroah-Hartman, linux-serial; +Cc: LKML, uclinux-dist-devel, Sonic Zhang
In-Reply-To: <1323750122-17698-1-git-send-email-sonic.adi@gmail.com>
From: Sonic Zhang <sonic.zhang@analog.com>
Blackfin uart supports automatic CTS trigger when hardware flow control is enabled.
No need to start and top tx in CTS interrupt. So, remote ASYNC_CTS_FLOW flag.
Signed-off-by: Sonic Zhang <sonic.zhang@analog.com>
---
drivers/tty/serial/bfin_uart.c | 17 ++++++++++++++---
1 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/drivers/tty/serial/bfin_uart.c b/drivers/tty/serial/bfin_uart.c
index dedd9ab..26953bf 100644
--- a/drivers/tty/serial/bfin_uart.c
+++ b/drivers/tty/serial/bfin_uart.c
@@ -116,11 +116,20 @@ static void bfin_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
static irqreturn_t bfin_serial_mctrl_cts_int(int irq, void *dev_id)
{
struct bfin_serial_port *uart = dev_id;
- unsigned int status;
-
- status = bfin_serial_get_mctrl(&uart->port);
+ unsigned int status = bfin_serial_get_mctrl(&uart->port);
#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
+ struct tty_struct *tty = uart->port.state->port.tty;
+
UART_CLEAR_SCTS(uart);
+ if (tty->hw_stopped) {
+ if (status) {
+ tty->hw_stopped = 0;
+ uart_write_wakeup(&uart->port);
+ }
+ } else {
+ if (!status)
+ tty->hw_stopped = 1;
+ }
#endif
uart_handle_cts_change(&uart->port, status & TIOCM_CTS);
@@ -1358,7 +1367,9 @@ static int bfin_serial_probe(struct platform_device *pdev)
uart->cts_pin = -1;
else {
uart->cts_pin = res->start;
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
uart->port.flags |= ASYNC_CTS_FLOW;
+#endif
}
res = platform_get_resource(pdev, IORESOURCE_IO, 1);
--
1.7.0.4
^ permalink raw reply related
* [PATCH 1/2 v3] serial: bfin-uart: Enable hardware automatic CTS only when CTS pin is available.
From: Sonic Zhang @ 2011-12-13 4:22 UTC (permalink / raw)
To: Greg Kroah-Hartman, linux-serial; +Cc: LKML, uclinux-dist-devel, Sonic Zhang
From: Sonic Zhang <sonic.zhang@analog.com>
Signed-off-by: Sonic Zhang <sonic.zhang@analog.com>
---
drivers/tty/serial/bfin_uart.c | 19 ++++++++++---------
1 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/drivers/tty/serial/bfin_uart.c b/drivers/tty/serial/bfin_uart.c
index abac237..dedd9ab 100644
--- a/drivers/tty/serial/bfin_uart.c
+++ b/drivers/tty/serial/bfin_uart.c
@@ -726,16 +726,17 @@ static int bfin_serial_startup(struct uart_port *port)
}
#endif
#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
- if (uart->cts_pin >= 0 && request_irq(uart->status_irq,
- bfin_serial_mctrl_cts_int,
- 0, "BFIN_UART_MODEM_STATUS", uart)) {
- uart->cts_pin = -1;
- pr_info("Unable to attach BlackFin UART Modem Status interrupt.\n");
- }
+ if (uart->cts_pin >= 0) {
+ if (request_irq(uart->status_irq, bfin_serial_mctrl_cts_int,
+ IRQF_DISABLED, "BFIN_UART_MODEM_STATUS", uart)) {
+ uart->cts_pin = -1;
+ dev_info(port->dev, "Unable to attach BlackFin UART Modem Status interrupt.\n");
+ }
- /* CTS RTS PINs are negative assertive. */
- UART_PUT_MCR(uart, ACTS);
- UART_SET_IER(uart, EDSSI);
+ /* CTS RTS PINs are negative assertive. */
+ UART_PUT_MCR(uart, ACTS);
+ UART_SET_IER(uart, EDSSI);
+ }
#endif
UART_SET_IER(uart, ERBFI);
--
1.7.0.4
^ permalink raw reply related
* [PATCH v5] tty: serial: imx: Allow UART to be a source for wakeup
From: Fabio Estevam @ 2011-12-13 3:23 UTC (permalink / raw)
To: linux-arm-kernel; +Cc: kernel, shawn.guo, alan, linux-serial, Fabio Estevam
In-Reply-To: <1323434541-27689-1-git-send-email-festevam@gmail.com>
Allow UART to be a source for wakeup from low power mode.
Tested on a MX27PDK by doing:
echo enabled > /sys/devices/platform/imx21-uart.0/tty/ttymxc0/power/wakeup
echo mem > /sys/power/state
and then pressing a key in the console will wakeup the sytem.
Suggested-by: Shawn Guo <shawn.guo@freescale.com>
Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com>
---
Changes since v4:
- Let serial core handle device_init_wakeup/device_set_wakeup_enable.
Changes since v3:
- Remove IMXUART_CANWAKE flag. Let userspace write in /sys/ file
in order to enable UART wakeup source.
Changes since v2:
- Remove incorrect enable_irq_wake from serial_imx_resume
Changes since v1:
- Pass the can-wake property via DT correctly
drivers/tty/serial/imx.c | 15 +++++++++++++++
1 files changed, 15 insertions(+), 0 deletions(-)
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 163fc90..0022bbd 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -566,6 +566,9 @@ static irqreturn_t imx_int(int irq, void *dev_id)
if (sts & USR1_RTSD)
imx_rtsint(irq, dev_id);
+ if (sts & USR1_AWAKE)
+ writel(USR1_AWAKE, sport->port.membase + USR1);
+
return IRQ_HANDLED;
}
@@ -1269,6 +1272,12 @@ static struct uart_driver imx_reg = {
static int serial_imx_suspend(struct platform_device *dev, pm_message_t state)
{
struct imx_port *sport = platform_get_drvdata(dev);
+ unsigned int val;
+
+ /* enable wakeup from i.MX UART */
+ val = readl(sport->port.membase + UCR3);
+ val |= UCR3_AWAKEN;
+ writel(val, sport->port.membase + UCR3);
if (sport)
uart_suspend_port(&imx_reg, &sport->port);
@@ -1279,7 +1288,13 @@ static int serial_imx_suspend(struct platform_device *dev, pm_message_t state)
static int serial_imx_resume(struct platform_device *dev)
{
struct imx_port *sport = platform_get_drvdata(dev);
+ unsigned int val;
+ /* disable wakeup from i.MX UART */
+ val = readl(sport->port.membase + UCR3);
+ val &= ~UCR3_AWAKEN;
+ writel(val, sport->port.membase + UCR3);
+
if (sport)
uart_resume_port(&imx_reg, &sport->port);
--
1.7.1
^ permalink raw reply related
* Re: [PATCH 01/16 v3] pmac_zilog: fix unexpected irq
From: Finn Thain @ 2011-12-13 1:24 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Geert Uytterhoeven, linux-m68k, linuxppc-dev, linux-serial
In-Reply-To: <1323720383.19891.21.camel@pasglop>
On Tue, 13 Dec 2011, Benjamin Herrenschmidt wrote:
> On Tue, 2011-12-13 at 00:34 +1100, Finn Thain wrote:
> > On Mon, 12 Dec 2011, Benjamin Herrenschmidt wrote:
> >
> > > Any chance you can test this patch ? I would not be surprised if it
> > > broke m68k since I had to do some of the changes in there "blind",
> > > so let me know... with this, I can again suspend/resume properly on
> > > a Pismo while using the internal modem among other things.
> >
> > The patch works on a PowerBook 520 given a few changes (below). This
> > PowerBook only has one serial port that I can test (the internal modem
> > is not supported on 68k Macs).
>
> Interesting. The modem is a soft-modem "geoport" or a hw serial modem ?
It's the latter.
> In the later case it's probably just a matter of finding the right GPIO
> bit in Apple ASIC to turn the power on :-)
Surely feasible, but not high on the list of missing hardware support.
>
> > Can you test a machine with two ports? The rest of my Mac hardware is
> > in storage since I moved house last week.
>
> I tried on 2 port powermacs, but I only have one adapter, so I've
> basically been running with one serial port open and shooting irda frame
> on the other (with nothing to check wether I got the frames on the other
> hand), oh well ...
>
> I'll apply your patch and commit via my tree.
I forgot to include this fix for your logging change.
Finn
Index: linux-git/drivers/tty/serial/pmac_zilog.c
===================================================================
--- linux-git.orig/drivers/tty/serial/pmac_zilog.c 2011-12-13 12:12:05.000000000 +1100
+++ linux-git/drivers/tty/serial/pmac_zilog.c 2011-12-13 12:13:29.000000000 +1100
@@ -99,6 +99,10 @@ MODULE_LICENSE("GPL");
#define PMACZILOG_NAME "ttyPZ"
#endif
+#define pmz_debug(fmt, arg...) pr_debug(PMACZILOG_NAME "%d: " fmt, uap->port.line, ## arg)
+#define pmz_error(fmt, arg...) pr_err(PMACZILOG_NAME "%d: " fmt, uap->port.line, ## arg)
+#define pmz_info(fmt, arg...) pr_info(PMACZILOG_NAME "%d: " fmt, uap->port.line, ## arg)
+
/*
* For the sake of early serial console, we can do a pre-probe
Index: linux-git/drivers/tty/serial/pmac_zilog.h
===================================================================
--- linux-git.orig/drivers/tty/serial/pmac_zilog.h 2011-12-13 12:12:05.000000000 +1100
+++ linux-git/drivers/tty/serial/pmac_zilog.h 2011-12-13 12:12:28.000000000 +1100
@@ -1,10 +1,6 @@
#ifndef __PMAC_ZILOG_H__
#define __PMAC_ZILOG_H__
-#define pmz_debug(fmt, arg...) pr_debug("ttyPZ%d: " fmt, uap->port.line, ## arg)
-#define pmz_error(fmt, arg...) pr_err("ttyPZ%d: " fmt, uap->port.line, ## arg)
-#define pmz_info(fmt, arg...) pr_info("ttyPZ%d: " fmt, uap->port.line, ## arg)
-
/*
* At most 2 ESCCs with 2 ports each
*/
^ permalink raw reply
* Re: [PATCH 01/10] GPIO: gpio-generic: Move initialization up to postcore
From: Janusz Krzysztofik @ 2011-12-13 0:15 UTC (permalink / raw)
To: Tony Lindgren
Cc: Grant Likely, linux-omap, linux-arm-kernel, linux-kernel,
Greg Kroah-Hartman, linux-serial
In-Reply-To: <20111212235544.GM32251@atomide.com>
On Tuesday 13 of December 2011 at 00:55:44, Tony Lindgren wrote:
> * Janusz Krzysztofik <jkrzyszt@tis.icnet.pl> [111212 15:13]:
> > On Tuesday 13 of December 2011 at 00:15:20, Tony Lindgren wrote:
> > >
> > > Might be worth checking if some board specific __initcall helps here
> > > too?
> >
> > If I only knew how I could insert a board specific __initcall between
> > two points from where the generic-gpio first, then the 8250 driver, are
> > called.
> >
> > Any hints?
>
> Hmm, can't you do all that in the order you want in
> ams_delta_modem_init()? Or make that into a late_initcall so
> you have generic-gpio available?
>
> It seems that the pieces of code you're talking about don't need
> to be initialized early, just needs to be done in the right
> order to get things working.
I think I've got it, thanks!
Janusz
^ permalink raw reply
* Re: [PATCH 1/2 v2] serial: bfin-uart: Enable hardware automatic CTS only when CTS pin is available.
From: Greg KH @ 2011-12-13 0:03 UTC (permalink / raw)
To: Sonic Zhang
Cc: Greg Kroah-Hartman, linux-serial, LKML, uclinux-dist-devel,
Sonic Zhang
In-Reply-To: <1323673191-9210-1-git-send-email-sonic.adi@gmail.com>
On Mon, Dec 12, 2011 at 02:59:50PM +0800, Sonic Zhang wrote:
> From: Sonic Zhang <sonic.zhang@analog.com>
>
> Signed-off-by: Sonic Zhang <sonic.zhang@analog.com>
> ---
> drivers/tty/serial/bfin_uart.c | 19 ++++++++++---------
> 1 files changed, 10 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/tty/serial/bfin_uart.c b/drivers/tty/serial/bfin_uart.c
> index abac237..a6c1c08 100644
> --- a/drivers/tty/serial/bfin_uart.c
> +++ b/drivers/tty/serial/bfin_uart.c
> @@ -726,16 +726,17 @@ static int bfin_serial_startup(struct uart_port *port)
> }
> #endif
> #ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
> - if (uart->cts_pin >= 0 && request_irq(uart->status_irq,
> - bfin_serial_mctrl_cts_int,
> - 0, "BFIN_UART_MODEM_STATUS", uart)) {
> - uart->cts_pin = -1;
> - pr_info("Unable to attach BlackFin UART Modem Status interrupt.\n");
> - }
> + if (uart->cts_pin >= 0) {
> + if (request_irq(uart->status_irq, bfin_serial_mctrl_cts_int,
> + IRQF_DISABLED, "BFIN_UART_MODEM_STATUS", uart)) {
> + uart->cts_pin = -1;
> + pr_info("Unable to attach BlackFin UART Modem Status interrupt.\n");
Please use dev_info() here instead, that properly identifies the exact
device you are having problems with.
thanks,
greg k-h
^ permalink raw reply
* Re: [PATCH 01/10] GPIO: gpio-generic: Move initialization up to postcore
From: Tony Lindgren @ 2011-12-12 23:55 UTC (permalink / raw)
To: Janusz Krzysztofik
Cc: Grant Likely, linux-omap, linux-arm-kernel, linux-kernel,
Greg Kroah-Hartman, linux-serial
In-Reply-To: <201112130044.02007.jkrzyszt@tis.icnet.pl>
* Janusz Krzysztofik <jkrzyszt@tis.icnet.pl> [111212 15:13]:
> On Tuesday 13 of December 2011 at 00:15:20, Tony Lindgren wrote:
> >
> > Might be worth checking if some board specific __initcall helps here
> > too?
>
> If I only knew how I could insert a board specific __initcall between
> two points from where the generic-gpio first, then the 8250 driver, are
> called.
>
> Any hints?
Hmm, can't you do all that in the order you want in
ams_delta_modem_init()? Or make that into a late_initcall so
you have generic-gpio available?
It seems that the pieces of code you're talking about don't need
to be initialized early, just needs to be done in the right
order to get things working.
Regards,
Tony
^ permalink raw reply
* Re: [PATCH 01/10] GPIO: gpio-generic: Move initialization up to postcore
From: Janusz Krzysztofik @ 2011-12-12 23:44 UTC (permalink / raw)
To: Tony Lindgren
Cc: Grant Likely, linux-omap, linux-arm-kernel, linux-kernel,
Greg Kroah-Hartman, linux-serial
In-Reply-To: <20111212231519.GK32251@atomide.com>
On Tuesday 13 of December 2011 at 00:15:20, Tony Lindgren wrote:
>
> Might be worth checking if some board specific __initcall helps here
> too?
If I only knew how I could insert a board specific __initcall between
two points from where the generic-gpio first, then the 8250 driver, are
called.
Any hints?
Thanks,
Janusz
^ permalink raw reply
* Re: [PATCH 01/10] GPIO: gpio-generic: Move initialization up to postcore
From: Tony Lindgren @ 2011-12-12 23:15 UTC (permalink / raw)
To: Janusz Krzysztofik
Cc: Grant Likely, linux-omap, linux-arm-kernel, linux-kernel,
Greg Kroah-Hartman, linux-serial
In-Reply-To: <201112130005.35386.jkrzyszt@tis.icnet.pl>
* Janusz Krzysztofik <jkrzyszt@tis.icnet.pl> [111212 14:36]:
> (adding Greg Kroah-Hartman and linux-serial@vger.kernel.org to Cc:)
>
> On Monday 12 of December 2011 at 19:04:56, Tony Lindgren wrote:
> > * Janusz Krzysztofik <jkrzyszt@tis.icnet.pl> [111211 11:41]:
> > > This will allow boards with custom memory mapped GPIO ports to set up
> > > and use those port pins while initializing devices from arch init.
> >
> > Care to explain a bit more why you need to initialize those devices
> > early on?
>
> Let me try.
>
> From patch 2/10 "ARM: OMAP1: ams-delta: Convert latches to
> basic_mmio_gpio":
>
> > @@ -307,8 +487,8 @@ static void __init ams_delta_init(void)
> > omap_serial_init();
> > omap_register_i2c_bus(1, 100, NULL, 0);
> >
> > - /* Clear latch2 (NAND, LCD, modem enable) */
> > - ams_delta_latch2_write(~0, 0);
> > + platform_add_devices(_latch_devices, ARRAY_SIZE(_latch_devices));
> > + BUG_ON(gpio_request_array(_latch_gpios, ARRAY_SIZE(_latch_gpios)));
> >
> > omap1_usb_init(&ams_delta_usb_config);
> > omap1_set_camera_info(&ams_delta_camera_platform_data);
>
> Here I'm accessing the latches from ams_delta_init() (.init_machine
> hook) with gpio_request_array() in order to:
> a) clear their contents,
> b) avoid accessing them, from ams_delta_latch_write(), never requested.
>
> I could imagine clearing their contents with something like
>
> *(volatile __u8 *) AMS_DELTA_LATCH2_VIRT = 0;
> *(volatile __u16 *) AMS_DELTA_LATCH2_VIRT = 0;
>
> instead, i.e., the way the old code used to, than accessing those GPIO
> pins not requested, until they are finally requested by drivers updated
> to use gpiolib with successive patche. Would this be acceptable?
Thanks for explaining, it's best to use gpio calls instead :)
How about just add some __initcall into your board-*.c file to
do the required setups a bit later? Just make sure you exit
early if (!machine_is...) fails.
> However,
> From patch 6/10 "ARM: OMAP1: ams-delta: Use GPIO API in modem setup":
>
> > @@ -482,6 +472,12 @@ static void __init ams_delta_init(void)
> > omap_writew(omap_readw(ARM_RSTCT1) | 0x0004, ARM_RSTCT1);
> > }
> >
> > +static void _modem_pm(struct uart_port *port, unsigned int state, unsigned old)
> > +{
> > + if (state != old)
> > + gpio_set_value(AMS_DELTA_GPIO_PIN_MODEM_NRESET, state == 0);
> > +}
> > +
> > static struct plat_serial8250_port ams_delta_modem_ports[] = {
> > {
> > .membase = IOMEM(_MODEM_VIRT),
> > @@ -492,6 +488,7 @@ static struct plat_serial8250_port ams_delta_modem_ports[] = {
> > .iotype = UPIO_MEM,
> > .regshift = 1,
> > .uartclk = BASE_BAUD * 16,
> > + .pm = _modem_pm,
> > },
> > { },
> > };
> > @@ -504,6 +501,24 @@ static struct platform_device ams_delta_modem_device = {
> > },
> > };
> >
> > +static struct gpio _modem_gpios[] __initconst = {
> > + {
> > + .gpio = AMS_DELTA_GPIO_PIN_MODEM_IRQ,
> > + .flags = GPIOF_DIR_IN,
> > + .label = "modem_irq",
> > + },
> > + {
> > + .gpio = AMS_DELTA_GPIO_PIN_MODEM_NRESET,
> > + .flags = GPIOF_OUT_INIT_HIGH,
> > + .label = "modem_nreset",
> > + },
> > + {
> > + .gpio = AMS_DELTA_GPIO_PIN_MODEM_CODEC,
> > + .flags = GPIOF_OUT_INIT_HIGH,
> > + .label = "modem_codec",
> > + },
> > +};
> > +
> > static int __init ams_delta_modem_init(void)
> > {
> > int err;
> > @@ -515,16 +530,11 @@ static int __init ams_delta_modem_init(void)
> > ams_delta_modem_ports[0].irq =
> > gpio_to_irq(AMS_DELTA_GPIO_PIN_MODEM_IRQ);
> >
> > - err = gpio_request(AMS_DELTA_GPIO_PIN_MODEM_IRQ, "modem");
> > + err = gpio_request_array(_modem_gpios, ARRAY_SIZE(_modem_gpios));
> > if (err) {
> > - pr_err("Couldn't request gpio pin for modem\n");
> > + pr_err("Couldn't request gpio pins for modem\n");
> > return err;
> > }
> > - gpio_direction_input(AMS_DELTA_GPIO_PIN_MODEM_IRQ);
> > -
> > - ams_delta_latch2_write(
> > - AMS_DELTA_LATCH2_MODEM_NRESET | AMS_DELTA_LATCH2_MODEM_CODEC,
> > - AMS_DELTA_LATCH2_MODEM_NRESET | AMS_DELTA_LATCH2_MODEM_CODEC);
> >
> > return platform_device_register(&ams_delta_modem_device);
> > }
>
> Before the change, only one GPIO pin, that IRQ, driven with omap_gpio
> driver which is registered from postcore, was gpio_request()ed. Now, two
> more, gpio-generic driven pins, are also requested _and_ initialized in
> order to make the modem accessible. The ams_delta_modem_init() is
> installed with arch_initcall().
>
> I could imagine initializing those modem pins the old way I've suggested
> above, but I can see no good solution to delegate calling of that
> gpio_request*() to the 8250 driver. For me, the only hook passed to the
> driver with platform_data that can be suitable is the .pm hook. However,
> when I tried to remove powering up the modem (rising up
> AMS_DELTA_GPIO_PIN_MODEM_NRESET) from the arch init and do this only
> from that .pm hook, the device was not detected, so I wonder if and when
> that hook is called, and if it is before probe, then perhaps powering
> up the modem chip from there is too late for the device to get up before
> being examined. But then, maybe if we initialize the pin the old way
> from arch init, it would be enough for the device to be detected, while
> consecutive open() response times may not be so critical. Perhaps Greg
> or another serial guru can shed some more light on this.
>
> But this way or another, we are talking about dirty hacks here IMHO.
Might be worth checking if some board specific __initcall helps here
too?
Regards,
Tony
^ permalink raw reply
* Re: [PATCH 01/10] GPIO: gpio-generic: Move initialization up to postcore
From: Janusz Krzysztofik @ 2011-12-12 23:05 UTC (permalink / raw)
To: Tony Lindgren
Cc: Grant Likely, linux-omap, linux-arm-kernel, linux-kernel,
Greg Kroah-Hartman, linux-serial
In-Reply-To: <20111212180456.GF31337@atomide.com>
(adding Greg Kroah-Hartman and linux-serial@vger.kernel.org to Cc:)
On Monday 12 of December 2011 at 19:04:56, Tony Lindgren wrote:
> * Janusz Krzysztofik <jkrzyszt@tis.icnet.pl> [111211 11:41]:
> > This will allow boards with custom memory mapped GPIO ports to set up
> > and use those port pins while initializing devices from arch init.
>
> Care to explain a bit more why you need to initialize those devices
> early on?
Let me try.
>From patch 2/10 "ARM: OMAP1: ams-delta: Convert latches to
basic_mmio_gpio":
> @@ -307,8 +487,8 @@ static void __init ams_delta_init(void)
> omap_serial_init();
> omap_register_i2c_bus(1, 100, NULL, 0);
>
> - /* Clear latch2 (NAND, LCD, modem enable) */
> - ams_delta_latch2_write(~0, 0);
> + platform_add_devices(_latch_devices, ARRAY_SIZE(_latch_devices));
> + BUG_ON(gpio_request_array(_latch_gpios, ARRAY_SIZE(_latch_gpios)));
>
> omap1_usb_init(&ams_delta_usb_config);
> omap1_set_camera_info(&ams_delta_camera_platform_data);
Here I'm accessing the latches from ams_delta_init() (.init_machine
hook) with gpio_request_array() in order to:
a) clear their contents,
b) avoid accessing them, from ams_delta_latch_write(), never requested.
I could imagine clearing their contents with something like
*(volatile __u8 *) AMS_DELTA_LATCH2_VIRT = 0;
*(volatile __u16 *) AMS_DELTA_LATCH2_VIRT = 0;
instead, i.e., the way the old code used to, than accessing those GPIO
pins not requested, until they are finally requested by drivers updated
to use gpiolib with successive patche. Would this be acceptable?
However,
>From patch 6/10 "ARM: OMAP1: ams-delta: Use GPIO API in modem setup":
> @@ -482,6 +472,12 @@ static void __init ams_delta_init(void)
> omap_writew(omap_readw(ARM_RSTCT1) | 0x0004, ARM_RSTCT1);
> }
>
> +static void _modem_pm(struct uart_port *port, unsigned int state, unsigned old)
> +{
> + if (state != old)
> + gpio_set_value(AMS_DELTA_GPIO_PIN_MODEM_NRESET, state == 0);
> +}
> +
> static struct plat_serial8250_port ams_delta_modem_ports[] = {
> {
> .membase = IOMEM(_MODEM_VIRT),
> @@ -492,6 +488,7 @@ static struct plat_serial8250_port ams_delta_modem_ports[] = {
> .iotype = UPIO_MEM,
> .regshift = 1,
> .uartclk = BASE_BAUD * 16,
> + .pm = _modem_pm,
> },
> { },
> };
> @@ -504,6 +501,24 @@ static struct platform_device ams_delta_modem_device = {
> },
> };
>
> +static struct gpio _modem_gpios[] __initconst = {
> + {
> + .gpio = AMS_DELTA_GPIO_PIN_MODEM_IRQ,
> + .flags = GPIOF_DIR_IN,
> + .label = "modem_irq",
> + },
> + {
> + .gpio = AMS_DELTA_GPIO_PIN_MODEM_NRESET,
> + .flags = GPIOF_OUT_INIT_HIGH,
> + .label = "modem_nreset",
> + },
> + {
> + .gpio = AMS_DELTA_GPIO_PIN_MODEM_CODEC,
> + .flags = GPIOF_OUT_INIT_HIGH,
> + .label = "modem_codec",
> + },
> +};
> +
> static int __init ams_delta_modem_init(void)
> {
> int err;
> @@ -515,16 +530,11 @@ static int __init ams_delta_modem_init(void)
> ams_delta_modem_ports[0].irq =
> gpio_to_irq(AMS_DELTA_GPIO_PIN_MODEM_IRQ);
>
> - err = gpio_request(AMS_DELTA_GPIO_PIN_MODEM_IRQ, "modem");
> + err = gpio_request_array(_modem_gpios, ARRAY_SIZE(_modem_gpios));
> if (err) {
> - pr_err("Couldn't request gpio pin for modem\n");
> + pr_err("Couldn't request gpio pins for modem\n");
> return err;
> }
> - gpio_direction_input(AMS_DELTA_GPIO_PIN_MODEM_IRQ);
> -
> - ams_delta_latch2_write(
> - AMS_DELTA_LATCH2_MODEM_NRESET | AMS_DELTA_LATCH2_MODEM_CODEC,
> - AMS_DELTA_LATCH2_MODEM_NRESET | AMS_DELTA_LATCH2_MODEM_CODEC);
>
> return platform_device_register(&ams_delta_modem_device);
> }
Before the change, only one GPIO pin, that IRQ, driven with omap_gpio
driver which is registered from postcore, was gpio_request()ed. Now, two
more, gpio-generic driven pins, are also requested _and_ initialized in
order to make the modem accessible. The ams_delta_modem_init() is
installed with arch_initcall().
I could imagine initializing those modem pins the old way I've suggested
above, but I can see no good solution to delegate calling of that
gpio_request*() to the 8250 driver. For me, the only hook passed to the
driver with platform_data that can be suitable is the .pm hook. However,
when I tried to remove powering up the modem (rising up
AMS_DELTA_GPIO_PIN_MODEM_NRESET) from the arch init and do this only
from that .pm hook, the device was not detected, so I wonder if and when
that hook is called, and if it is before probe, then perhaps powering
up the modem chip from there is too late for the device to get up before
being examined. But then, maybe if we initialize the pin the old way
from arch init, it would be enough for the device to be detected, while
consecutive open() response times may not be so critical. Perhaps Greg
or another serial guru can shed some more light on this.
But this way or another, we are talking about dirty hacks here IMHO.
Thanks,
Janusz
^ permalink raw reply
* Re: [PATCH 01/16 v3] pmac_zilog: fix unexpected irq
From: Benjamin Herrenschmidt @ 2011-12-12 20:06 UTC (permalink / raw)
To: Finn Thain; +Cc: Geert Uytterhoeven, linux-m68k, linuxppc-dev, linux-serial
In-Reply-To: <alpine.LNX.2.00.1112130020000.2550@nippy.intranet>
On Tue, 2011-12-13 at 00:34 +1100, Finn Thain wrote:
> On Mon, 12 Dec 2011, Benjamin Herrenschmidt wrote:
>
> > Any chance you can test this patch ? I would not be surprised if it
> > broke m68k since I had to do some of the changes in there "blind", so
> > let me know... with this, I can again suspend/resume properly on a Pismo
> > while using the internal modem among other things.
>
> The patch works on a PowerBook 520 given a few changes (below). This
> PowerBook only has one serial port that I can test (the internal modem is
> not supported on 68k Macs).
Interesting. The modem is a soft-modem "geoport" or a hw serial modem ?
In the later case it's probably just a matter of finding the right GPIO
bit in Apple ASIC to turn the power on :-)
> Can you test a machine with two ports? The
> rest of my Mac hardware is in storage since I moved house last week.
I tried on 2 port powermacs, but I only have one adapter, so I've
basically been running with one serial port open and shooting irda frame
on the other (with nothing to check wether I got the frames on the other
hand), oh well ...
I'll apply your patch and commit via my tree.
Cheers,
Ben.
> Finn
>
>
> Index: linux-git/drivers/tty/serial/pmac_zilog.c
> ===================================================================
> --- linux-git.orig/drivers/tty/serial/pmac_zilog.c 2011-12-13 00:18:02.000000000 +1100
> +++ linux-git/drivers/tty/serial/pmac_zilog.c 2011-12-13 00:23:55.000000000 +1100
> @@ -1705,8 +1705,8 @@ static int __init pmz_init_port(struct u
> struct resource *r_ports;
> int irq;
>
> - r_ports = platform_get_resource(uap->node, IORESOURCE_MEM, 0);
> - irq = platform_get_irq(uap->node, 0);
> + r_ports = platform_get_resource(uap->pdev, IORESOURCE_MEM, 0);
> + irq = platform_get_irq(uap->pdev, 0);
> if (!r_ports || !irq)
> return -ENODEV;
>
> @@ -1763,8 +1763,10 @@ static void pmz_dispose_port(struct uart
>
> static int __init pmz_attach(struct platform_device *pdev)
> {
> + struct uart_pmac_port *uap;
> int i;
>
> + /* Iterate the pmz_ports array to find a matching entry */
> for (i = 0; i < pmz_ports_count; i++)
> if (pmz_ports[i].pdev == pdev)
> break;
> @@ -1773,15 +1775,23 @@ static int __init pmz_attach(struct plat
>
> uap = &pmz_ports[i];
> uap->port.dev = &pdev->dev;
> - dev_set_drvdata(&mdev->ofdev.dev, uap);
> + platform_set_drvdata(pdev, uap);
>
> - return uart_add_one_port(&pmz_uart_reg,
> - &pmz_ports[i]->port);
> + return uart_add_one_port(&pmz_uart_reg, &uap->port);
> }
>
> static int __exit pmz_detach(struct platform_device *pdev)
> {
> + struct uart_pmac_port *uap = platform_get_drvdata(pdev);
> +
> + if (!uap)
> + return -ENODEV;
> +
> uart_remove_one_port(&pmz_uart_reg, &uap->port);
> +
> + platform_set_drvdata(pdev, NULL);
> + uap->port.dev = NULL;
> +
> return 0;
> }
>
> @@ -1918,8 +1928,13 @@ static void __exit exit_pmz(void)
>
> for (i = 0; i < pmz_ports_count; i++) {
> struct uart_pmac_port *uport = &pmz_ports[i];
> +#ifdef CONFIG_PPC_PMAC
> if (uport->node != NULL)
> pmz_dispose_port(uport);
> +#else
> + if (uport->pdev != NULL)
> + pmz_dispose_port(uport);
> +#endif
> }
> /* Unregister UART driver */
> uart_unregister_driver(&pmz_uart_reg);
> @@ -1993,6 +2008,9 @@ static int __init pmz_console_setup(stru
> #ifdef CONFIG_PPC_PMAC
> if (uap->node == NULL)
> return -ENODEV;
> +#else
> + if (uap->pdev == NULL)
> + return -ENODEV;
> #endif
> port = &uap->port;
>
> Index: linux-git/drivers/tty/serial/pmac_zilog.h
> ===================================================================
> --- linux-git.orig/drivers/tty/serial/pmac_zilog.h 2011-12-13 00:18:02.000000000 +1100
> +++ linux-git/drivers/tty/serial/pmac_zilog.h 2011-12-13 00:23:55.000000000 +1100
> @@ -1,18 +1,9 @@
> #ifndef __PMAC_ZILOG_H__
> #define __PMAC_ZILOG_H__
>
> -#ifdef CONFIG_PPC_PMAC
> -/* We cannot use dev_* because this can be called early, way before
> - * we are matched with a device (when using it as a kernel console)
> - */
> #define pmz_debug(fmt, arg...) pr_debug("ttyPZ%d: " fmt, uap->port.line, ## arg)
> #define pmz_error(fmt, arg...) pr_err("ttyPZ%d: " fmt, uap->port.line, ## arg)
> #define pmz_info(fmt, arg...) pr_info("ttyPZ%d: " fmt, uap->port.line, ## arg)
> -#else
> -#define pmz_debug(fmt, arg...) dev_dbg(&uap->node->dev, fmt, ## arg)
> -#define pmz_error(fmt, arg...) dev_err(&uap->node->dev, fmt, ## arg)
> -#define pmz_info(fmt, arg...) dev_info(&uap->node->dev, fmt, ## arg)
> -#endif
>
> /*
> * At most 2 ESCCs with 2 ports each
^ permalink raw reply
* Re: [PATCH RESEND 0/8] serial: 8250: support hw-based RS485 direction control
From: Claudio Scordino @ 2011-12-12 14:42 UTC (permalink / raw)
To: Wolfram Sang; +Cc: linux-serial, linux-kernel, Greg KH, Alan Cox
In-Reply-To: <1323450440-414-1-git-send-email-w.sang@pengutronix.de>
Il 09/12/2011 18:07, Wolfram Sang ha scritto:
> Some 8250-variants control the direction pin for RS485 in hardware. Linux has
> RS485 support these days, so update the 8250-driver to adhere to that.
>
> Code is based on 3.2-rc4, tested on a OMAP-based custom board with a 16V2750.
> A git tree can be found here:
>
> git://git.pengutronix.de/git/wsa/linux-2.6.git 8250_rs485
>
> There is no code change since the initial post of this series. I updated some
> of the patch descriptions, though. A kind-of-ack from Claudio can be found here
> [1]. Please consider for inclusion.
Hi Wolfram,
since the code has not been changed, my opinion remains that it is fine
and it should enter mainline.
Best regards,
Claudio
^ permalink raw reply
* Re: [PATCH 01/16 v3] pmac_zilog: fix unexpected irq
From: Finn Thain @ 2011-12-12 13:34 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Geert Uytterhoeven, linux-m68k, linuxppc-dev, linux-serial
In-Reply-To: <1323647315.19891.10.camel@pasglop>
On Mon, 12 Dec 2011, Benjamin Herrenschmidt wrote:
> Any chance you can test this patch ? I would not be surprised if it
> broke m68k since I had to do some of the changes in there "blind", so
> let me know... with this, I can again suspend/resume properly on a Pismo
> while using the internal modem among other things.
The patch works on a PowerBook 520 given a few changes (below). This
PowerBook only has one serial port that I can test (the internal modem is
not supported on 68k Macs). Can you test a machine with two ports? The
rest of my Mac hardware is in storage since I moved house last week.
Finn
Index: linux-git/drivers/tty/serial/pmac_zilog.c
===================================================================
--- linux-git.orig/drivers/tty/serial/pmac_zilog.c 2011-12-13 00:18:02.000000000 +1100
+++ linux-git/drivers/tty/serial/pmac_zilog.c 2011-12-13 00:23:55.000000000 +1100
@@ -1705,8 +1705,8 @@ static int __init pmz_init_port(struct u
struct resource *r_ports;
int irq;
- r_ports = platform_get_resource(uap->node, IORESOURCE_MEM, 0);
- irq = platform_get_irq(uap->node, 0);
+ r_ports = platform_get_resource(uap->pdev, IORESOURCE_MEM, 0);
+ irq = platform_get_irq(uap->pdev, 0);
if (!r_ports || !irq)
return -ENODEV;
@@ -1763,8 +1763,10 @@ static void pmz_dispose_port(struct uart
static int __init pmz_attach(struct platform_device *pdev)
{
+ struct uart_pmac_port *uap;
int i;
+ /* Iterate the pmz_ports array to find a matching entry */
for (i = 0; i < pmz_ports_count; i++)
if (pmz_ports[i].pdev == pdev)
break;
@@ -1773,15 +1775,23 @@ static int __init pmz_attach(struct plat
uap = &pmz_ports[i];
uap->port.dev = &pdev->dev;
- dev_set_drvdata(&mdev->ofdev.dev, uap);
+ platform_set_drvdata(pdev, uap);
- return uart_add_one_port(&pmz_uart_reg,
- &pmz_ports[i]->port);
+ return uart_add_one_port(&pmz_uart_reg, &uap->port);
}
static int __exit pmz_detach(struct platform_device *pdev)
{
+ struct uart_pmac_port *uap = platform_get_drvdata(pdev);
+
+ if (!uap)
+ return -ENODEV;
+
uart_remove_one_port(&pmz_uart_reg, &uap->port);
+
+ platform_set_drvdata(pdev, NULL);
+ uap->port.dev = NULL;
+
return 0;
}
@@ -1918,8 +1928,13 @@ static void __exit exit_pmz(void)
for (i = 0; i < pmz_ports_count; i++) {
struct uart_pmac_port *uport = &pmz_ports[i];
+#ifdef CONFIG_PPC_PMAC
if (uport->node != NULL)
pmz_dispose_port(uport);
+#else
+ if (uport->pdev != NULL)
+ pmz_dispose_port(uport);
+#endif
}
/* Unregister UART driver */
uart_unregister_driver(&pmz_uart_reg);
@@ -1993,6 +2008,9 @@ static int __init pmz_console_setup(stru
#ifdef CONFIG_PPC_PMAC
if (uap->node == NULL)
return -ENODEV;
+#else
+ if (uap->pdev == NULL)
+ return -ENODEV;
#endif
port = &uap->port;
Index: linux-git/drivers/tty/serial/pmac_zilog.h
===================================================================
--- linux-git.orig/drivers/tty/serial/pmac_zilog.h 2011-12-13 00:18:02.000000000 +1100
+++ linux-git/drivers/tty/serial/pmac_zilog.h 2011-12-13 00:23:55.000000000 +1100
@@ -1,18 +1,9 @@
#ifndef __PMAC_ZILOG_H__
#define __PMAC_ZILOG_H__
-#ifdef CONFIG_PPC_PMAC
-/* We cannot use dev_* because this can be called early, way before
- * we are matched with a device (when using it as a kernel console)
- */
#define pmz_debug(fmt, arg...) pr_debug("ttyPZ%d: " fmt, uap->port.line, ## arg)
#define pmz_error(fmt, arg...) pr_err("ttyPZ%d: " fmt, uap->port.line, ## arg)
#define pmz_info(fmt, arg...) pr_info("ttyPZ%d: " fmt, uap->port.line, ## arg)
-#else
-#define pmz_debug(fmt, arg...) dev_dbg(&uap->node->dev, fmt, ## arg)
-#define pmz_error(fmt, arg...) dev_err(&uap->node->dev, fmt, ## arg)
-#define pmz_info(fmt, arg...) dev_info(&uap->node->dev, fmt, ## arg)
-#endif
/*
* At most 2 ESCCs with 2 ports each
^ permalink raw reply
* Xmas Lening Aanbieding
From: Joseph Evans @ 2011-12-12 13:12 UTC (permalink / raw)
Wir sind auf dem XAMS Kredit Angebot mit so viel Bonus, bitte
kontaktieren Sie mich, wenn Sie tun müssen, jede Form von Darlehen von
unserer Firma.
Grüße
We are on our xams loan special offer with so much bonus, please do
contact me if you do need any form of loan from our firm.
Regards
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH 1/2 v2] serial: bfin-uart: Enable hardware automatic CTS only when CTS pin is available.
From: Sonic Zhang @ 2011-12-12 6:59 UTC (permalink / raw)
To: Greg Kroah-Hartman, linux-serial; +Cc: LKML, uclinux-dist-devel, Sonic Zhang
From: Sonic Zhang <sonic.zhang@analog.com>
Signed-off-by: Sonic Zhang <sonic.zhang@analog.com>
---
drivers/tty/serial/bfin_uart.c | 19 ++++++++++---------
1 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/drivers/tty/serial/bfin_uart.c b/drivers/tty/serial/bfin_uart.c
index abac237..a6c1c08 100644
--- a/drivers/tty/serial/bfin_uart.c
+++ b/drivers/tty/serial/bfin_uart.c
@@ -726,16 +726,17 @@ static int bfin_serial_startup(struct uart_port *port)
}
#endif
#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
- if (uart->cts_pin >= 0 && request_irq(uart->status_irq,
- bfin_serial_mctrl_cts_int,
- 0, "BFIN_UART_MODEM_STATUS", uart)) {
- uart->cts_pin = -1;
- pr_info("Unable to attach BlackFin UART Modem Status interrupt.\n");
- }
+ if (uart->cts_pin >= 0) {
+ if (request_irq(uart->status_irq, bfin_serial_mctrl_cts_int,
+ IRQF_DISABLED, "BFIN_UART_MODEM_STATUS", uart)) {
+ uart->cts_pin = -1;
+ pr_info("Unable to attach BlackFin UART Modem Status interrupt.\n");
+ }
- /* CTS RTS PINs are negative assertive. */
- UART_PUT_MCR(uart, ACTS);
- UART_SET_IER(uart, EDSSI);
+ /* CTS RTS PINs are negative assertive. */
+ UART_PUT_MCR(uart, ACTS);
+ UART_SET_IER(uart, EDSSI);
+ }
#endif
UART_SET_IER(uart, ERBFI);
--
1.7.0.4
^ permalink raw reply related
* [PATCH 2/2 v2] serial: bfin-uart: Remove ASYNC_CTS_FLOW flag for hardware automatic CTS.
From: Sonic Zhang @ 2011-12-12 6:59 UTC (permalink / raw)
To: Greg Kroah-Hartman, linux-serial; +Cc: LKML, uclinux-dist-devel, Sonic Zhang
In-Reply-To: <1323673191-9210-1-git-send-email-sonic.adi@gmail.com>
From: Sonic Zhang <sonic.zhang@analog.com>
Blackfin uart supports automatic CTS trigger when hardware flow control is enabled.
No need to start and top tx in CTS interrupt. So, remote ASYNC_CTS_FLOW flag.
Signed-off-by: Sonic Zhang <sonic.zhang@analog.com>
---
drivers/tty/serial/bfin_uart.c | 17 ++++++++++++++---
1 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/drivers/tty/serial/bfin_uart.c b/drivers/tty/serial/bfin_uart.c
index a6c1c08..6bb3698 100644
--- a/drivers/tty/serial/bfin_uart.c
+++ b/drivers/tty/serial/bfin_uart.c
@@ -116,11 +116,20 @@ static void bfin_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
static irqreturn_t bfin_serial_mctrl_cts_int(int irq, void *dev_id)
{
struct bfin_serial_port *uart = dev_id;
- unsigned int status;
-
- status = bfin_serial_get_mctrl(&uart->port);
+ unsigned int status = bfin_serial_get_mctrl(&uart->port);
#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
+ struct tty_struct *tty = uart->port.state->port.tty;
+
UART_CLEAR_SCTS(uart);
+ if (tty->hw_stopped) {
+ if (status) {
+ tty->hw_stopped = 0;
+ uart_write_wakeup(&uart->port);
+ }
+ } else {
+ if (!status)
+ tty->hw_stopped = 1;
+ }
#endif
uart_handle_cts_change(&uart->port, status & TIOCM_CTS);
@@ -1358,7 +1367,9 @@ static int bfin_serial_probe(struct platform_device *pdev)
uart->cts_pin = -1;
else {
uart->cts_pin = res->start;
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
uart->port.flags |= ASYNC_CTS_FLOW;
+#endif
}
res = platform_get_resource(pdev, IORESOURCE_IO, 1);
--
1.7.0.4
^ permalink raw reply related
* Re: [PATCH 2/2] serial: bfin-uart: Remove ASYNC_CTS_FLOW flag for hardware automatic CTS.
From: Sonic Zhang @ 2011-12-12 5:20 UTC (permalink / raw)
To: Alan Cox
Cc: Greg Kroah-Hartman, linux-serial, LKML, uclinux-dist-devel,
Sonic Zhang
In-Reply-To: <20111209111205.04780196@pyramind.ukuu.org.uk>
Hi Alan,
On Fri, Dec 9, 2011 at 7:12 PM, Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:
>> +#ifdef CONFIG_SERIAL_BFIN_CTSRTS
>> uart->port.flags |= ASYNC_CTS_FLOW;
>> +#endif
>
> As an aside could the cts/hard cts etc be passed as properties to the
> platform device rather than ifdeffed ?
>
> Alan
As Mike mentioned, these Macros are used to keep the code smaller when
user doesn't want to enable UART flow control feature.
I will sent out V2 against the latest kernel next tree.
Sonic
^ permalink raw reply
* Re: [PATCH 01/16 v3] pmac_zilog: fix unexpected irq
From: Benjamin Herrenschmidt @ 2011-12-11 23:55 UTC (permalink / raw)
To: Finn Thain; +Cc: Geert Uytterhoeven, linux-m68k, linuxppc-dev, linux-serial
In-Reply-To: <1323647315.19891.10.camel@pasglop>
On Mon, 2011-12-12 at 10:48 +1100, Benjamin Herrenschmidt wrote:
> Any chance you can test this patch ? I would not be surprised if it
> broke m68k since I had to do some of the changes in there "blind",
> so let me know... with this, I can again suspend/resume properly on
> a Pismo while using the internal modem among other things.
..../....
Forgot to commit a fix before sending, but it's a trivial one:
> -#ifdef DEBUG_HARD
> +#ifde DEBUG_HARD
> pmz_debug("irq, r3: %x\n", r3);
> #endif
Remove that hunk :-)
Cheers,
Ben.
^ permalink raw reply
* Re: [PATCH 01/16 v3] pmac_zilog: fix unexpected irq
From: Benjamin Herrenschmidt @ 2011-12-11 23:48 UTC (permalink / raw)
To: Finn Thain; +Cc: Geert Uytterhoeven, linux-m68k, linuxppc-dev, linux-serial
In-Reply-To: <alpine.LNX.2.00.1112082128330.2357@nippy.intranet>
Any chance you can test this patch ? I would not be surprised if it
broke m68k since I had to do some of the changes in there "blind",
so let me know... with this, I can again suspend/resume properly on
a Pismo while using the internal modem among other things.
>From c2dbe7117bb94c59a4b2a215fc87fe7eabb7658d Mon Sep 17 00:00:00 2001
From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Date: Mon, 12 Dec 2011 10:44:08 +1100
Subject: [PATCH 2/2] tty/serial/pmac_zilog: Fix suspend & resume
This patch reworks & simplifies pmac_zilog handling of suspend/resume,
essentially removing all the specific code in there and using the
generic uart helpers.
This required properly registering the tty as a child of the macio (or platform)
device, so I had to delay the registration a bit (we used to register the ports
very very early). We still register the kernel console early though.
I removed a couple of unused or useless flags as well, relying on the
core to not call us when asleep. I also removed the essentially useless
interrupt mutex, simplifying the locking a bit.
I removed some code for handling unexpected interrupt which should never
be hit and could potentially be harmful (causing us to access a register
on a powered off SCC). We diable port interrupts on close always so there
should be no need to drain data on a closed port.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
drivers/tty/serial/pmac_zilog.c | 350 ++++++++++-----------------------------
drivers/tty/serial/pmac_zilog.h | 18 +-
2 files changed, 99 insertions(+), 269 deletions(-)
diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c
index 51941f0..46cb39b 100644
--- a/drivers/tty/serial/pmac_zilog.c
+++ b/drivers/tty/serial/pmac_zilog.c
@@ -106,7 +106,6 @@ MODULE_LICENSE("GPL");
*/
static struct uart_pmac_port pmz_ports[MAX_ZS_PORTS];
static int pmz_ports_count;
-static DEFINE_MUTEX(pmz_irq_mutex);
static struct uart_driver pmz_uart_reg = {
.owner = THIS_MODULE,
@@ -126,9 +125,6 @@ static void pmz_load_zsregs(struct uart_pmac_port *uap, u8 *regs)
{
int i;
- if (ZS_IS_ASLEEP(uap))
- return;
-
/* Let pending transmits finish. */
for (i = 0; i < 1000; i++) {
unsigned char stat = read_zsreg(uap, R1);
@@ -234,26 +230,6 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap)
unsigned char ch, r1, drop, error, flag;
int loops = 0;
- /* The interrupt can be enabled when the port isn't open, typically
- * that happens when using one port is open and the other closed (stale
- * interrupt) or when one port is used as a console.
- */
- if (!ZS_IS_OPEN(uap)) {
- pmz_debug("pmz: draining input\n");
- /* Port is closed, drain input data */
- for (;;) {
- if ((++loops) > 1000)
- goto flood;
- (void)read_zsreg(uap, R1);
- write_zsreg(uap, R0, ERR_RES);
- (void)read_zsdata(uap);
- ch = read_zsreg(uap, R0);
- if (!(ch & Rx_CH_AV))
- break;
- }
- return NULL;
- }
-
/* Sanity check, make sure the old bug is no longer happening */
if (uap->port.state == NULL || uap->port.state->port.tty == NULL) {
WARN_ON(1);
@@ -393,8 +369,6 @@ static void pmz_transmit_chars(struct uart_pmac_port *uap)
{
struct circ_buf *xmit;
- if (ZS_IS_ASLEEP(uap))
- return;
if (ZS_IS_CONS(uap)) {
unsigned char status = read_zsreg(uap, R0);
@@ -485,12 +459,16 @@ static irqreturn_t pmz_interrupt(int irq, void *dev_id)
spin_lock(&uap_a->port.lock);
r3 = read_zsreg(uap_a, R3);
-#ifdef DEBUG_HARD
+#ifde DEBUG_HARD
pmz_debug("irq, r3: %x\n", r3);
#endif
/* Channel A */
tty = NULL;
if (r3 & (CHAEXT | CHATxIP | CHARxIP)) {
+ if (!ZS_IS_OPEN(uap_a)) {
+ pmz_debug("ChanA interrupt while open !\n");
+ goto skip_a;
+ }
write_zsreg(uap_a, R0, RES_H_IUS);
zssync(uap_a);
if (r3 & CHAEXT)
@@ -501,16 +479,21 @@ static irqreturn_t pmz_interrupt(int irq, void *dev_id)
pmz_transmit_chars(uap_a);
rc = IRQ_HANDLED;
}
+ skip_a:
spin_unlock(&uap_a->port.lock);
if (tty != NULL)
tty_flip_buffer_push(tty);
- if (uap_b->node == NULL)
+ if (!uap_b)
goto out;
spin_lock(&uap_b->port.lock);
tty = NULL;
if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) {
+ if (!ZS_IS_OPEN(uap_a)) {
+ pmz_debug("ChanB interrupt while open !\n");
+ goto skip_b;
+ }
write_zsreg(uap_b, R0, RES_H_IUS);
zssync(uap_b);
if (r3 & CHBEXT)
@@ -521,14 +504,12 @@ static irqreturn_t pmz_interrupt(int irq, void *dev_id)
pmz_transmit_chars(uap_b);
rc = IRQ_HANDLED;
}
+ skip_b:
spin_unlock(&uap_b->port.lock);
if (tty != NULL)
tty_flip_buffer_push(tty);
out:
-#ifdef DEBUG_HARD
- pmz_debug("irq done.\n");
-#endif
return rc;
}
@@ -553,12 +534,8 @@ static inline u8 pmz_peek_status(struct uart_pmac_port *uap)
*/
static unsigned int pmz_tx_empty(struct uart_port *port)
{
- struct uart_pmac_port *uap = to_pmz(port);
unsigned char status;
- if (ZS_IS_ASLEEP(uap) || uap->node == NULL)
- return TIOCSER_TEMT;
-
status = pmz_peek_status(to_pmz(port));
if (status & Tx_BUF_EMP)
return TIOCSER_TEMT;
@@ -580,8 +557,7 @@ static void pmz_set_mctrl(struct uart_port *port, unsigned int mctrl)
if (ZS_IS_IRDA(uap))
return;
/* We get called during boot with a port not up yet */
- if (ZS_IS_ASLEEP(uap) ||
- !(ZS_IS_OPEN(uap) || ZS_IS_CONS(uap)))
+ if (!(ZS_IS_OPEN(uap) || ZS_IS_CONS(uap)))
return;
set_bits = clear_bits = 0;
@@ -600,8 +576,7 @@ static void pmz_set_mctrl(struct uart_port *port, unsigned int mctrl)
/* NOTE: Not subject to 'transmitter active' rule. */
uap->curregs[R5] |= set_bits;
uap->curregs[R5] &= ~clear_bits;
- if (ZS_IS_ASLEEP(uap))
- return;
+
write_zsreg(uap, R5, uap->curregs[R5]);
pmz_debug("pmz_set_mctrl: set bits: %x, clear bits: %x -> %x\n",
set_bits, clear_bits, uap->curregs[R5]);
@@ -619,9 +594,6 @@ static unsigned int pmz_get_mctrl(struct uart_port *port)
unsigned char status;
unsigned int ret;
- if (ZS_IS_ASLEEP(uap) || uap->node == NULL)
- return 0;
-
status = read_zsreg(uap, R0);
ret = 0;
@@ -659,9 +631,6 @@ static void pmz_start_tx(struct uart_port *port)
uap->flags |= PMACZILOG_FLAG_TX_ACTIVE;
uap->flags &= ~PMACZILOG_FLAG_TX_STOPPED;
- if (ZS_IS_ASLEEP(uap) || uap->node == NULL)
- return;
-
status = read_zsreg(uap, R0);
/* TX busy? Just wait for the TX done interrupt. */
@@ -700,9 +669,6 @@ static void pmz_stop_rx(struct uart_port *port)
{
struct uart_pmac_port *uap = to_pmz(port);
- if (ZS_IS_ASLEEP(uap) || uap->node == NULL)
- return;
-
pmz_debug("pmz: stop_rx()()\n");
/* Disable all RX interrupts. */
@@ -721,14 +687,12 @@ static void pmz_enable_ms(struct uart_port *port)
struct uart_pmac_port *uap = to_pmz(port);
unsigned char new_reg;
- if (ZS_IS_IRDA(uap) || uap->node == NULL)
+ if (ZS_IS_IRDA(uap))
return;
new_reg = uap->curregs[R15] | (DCDIE | SYNCIE | CTSIE);
if (new_reg != uap->curregs[R15]) {
uap->curregs[R15] = new_reg;
- if (ZS_IS_ASLEEP(uap))
- return;
/* NOTE: Not subject to 'transmitter active' rule. */
write_zsreg(uap, R15, uap->curregs[R15]);
}
@@ -744,8 +708,6 @@ static void pmz_break_ctl(struct uart_port *port, int break_state)
unsigned char set_bits, clear_bits, new_reg;
unsigned long flags;
- if (uap->node == NULL)
- return;
set_bits = clear_bits = 0;
if (break_state)
@@ -758,12 +720,6 @@ static void pmz_break_ctl(struct uart_port *port, int break_state)
new_reg = (uap->curregs[R5] | set_bits) & ~clear_bits;
if (new_reg != uap->curregs[R5]) {
uap->curregs[R5] = new_reg;
-
- /* NOTE: Not subject to 'transmitter active' rule. */
- if (ZS_IS_ASLEEP(uap)) {
- spin_unlock_irqrestore(&port->lock, flags);
- return;
- }
write_zsreg(uap, R5, uap->curregs[R5]);
}
@@ -937,14 +893,21 @@ static int __pmz_startup(struct uart_pmac_port *uap)
static void pmz_irda_reset(struct uart_pmac_port *uap)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&uap->port.lock, flags);
uap->curregs[R5] |= DTR;
write_zsreg(uap, R5, uap->curregs[R5]);
zssync(uap);
- mdelay(110);
+ spin_unlock_irqrestore(&uap->port.lock, flags);
+ msleep(110);
+
+ spin_lock_irqsave(&uap->port.lock, flags);
uap->curregs[R5] &= ~DTR;
write_zsreg(uap, R5, uap->curregs[R5]);
zssync(uap);
- mdelay(10);
+ spin_unlock_irqrestore(&uap->port.lock, flags);
+ msleep(10);
}
/*
@@ -959,13 +922,6 @@ static int pmz_startup(struct uart_port *port)
pmz_debug("pmz: startup()\n");
- if (ZS_IS_ASLEEP(uap))
- return -EAGAIN;
- if (uap->node == NULL)
- return -ENODEV;
-
- mutex_lock(&pmz_irq_mutex);
-
uap->flags |= PMACZILOG_FLAG_IS_OPEN;
/* A console is never powered down. Else, power up and
@@ -976,18 +932,14 @@ static int pmz_startup(struct uart_port *port)
pwr_delay = __pmz_startup(uap);
spin_unlock_irqrestore(&port->lock, flags);
}
-
- pmz_get_port_A(uap)->flags |= PMACZILOG_FLAG_IS_IRQ_ON;
+ sprintf(uap->irq_name, PMACZILOG_NAME"%d", uap->port.line);
if (request_irq(uap->port.irq, pmz_interrupt, IRQF_SHARED,
- "SCC", uap)) {
+ uap->irq_name, uap)) {
pmz_error("Unable to register zs interrupt handler.\n");
pmz_set_scc_power(uap, 0);
- mutex_unlock(&pmz_irq_mutex);
return -ENXIO;
}
- mutex_unlock(&pmz_irq_mutex);
-
/* Right now, we deal with delay by blocking here, I'll be
* smarter later on
*/
@@ -1017,26 +969,19 @@ static void pmz_shutdown(struct uart_port *port)
pmz_debug("pmz: shutdown()\n");
- if (uap->node == NULL)
- return;
-
- mutex_lock(&pmz_irq_mutex);
-
spin_lock_irqsave(&port->lock, flags);
- if (!ZS_IS_ASLEEP(uap)) {
- /* Disable interrupt requests for the channel */
- pmz_interrupt_control(uap, 0);
+ /* Disable interrupt requests for the channel */
+ pmz_interrupt_control(uap, 0);
- if (!ZS_IS_CONS(uap)) {
- /* Disable receiver and transmitter */
- uap->curregs[R3] &= ~RxENABLE;
- uap->curregs[R5] &= ~TxENABLE;
+ if (!ZS_IS_CONS(uap)) {
+ /* Disable receiver and transmitter */
+ uap->curregs[R3] &= ~RxENABLE;
+ uap->curregs[R5] &= ~TxENABLE;
- /* Disable break assertion */
- uap->curregs[R5] &= ~SND_BRK;
- pmz_maybe_update_regs(uap);
- }
+ /* Disable break assertion */
+ uap->curregs[R5] &= ~SND_BRK;
+ pmz_maybe_update_regs(uap);
}
spin_unlock_irqrestore(&port->lock, flags);
@@ -1048,16 +993,11 @@ static void pmz_shutdown(struct uart_port *port)
uap->flags &= ~PMACZILOG_FLAG_IS_OPEN;
- if (!ZS_IS_OPEN(uap->mate))
- pmz_get_port_A(uap)->flags &= ~PMACZILOG_FLAG_IS_IRQ_ON;
-
- if (!ZS_IS_ASLEEP(uap) && !ZS_IS_CONS(uap))
+ if (!ZS_IS_CONS(uap))
pmz_set_scc_power(uap, 0); /* Shut the chip down */
spin_unlock_irqrestore(&port->lock, flags);
- mutex_unlock(&pmz_irq_mutex);
-
pmz_debug("pmz: shutdown() done.\n");
}
@@ -1305,9 +1245,6 @@ static void __pmz_set_termios(struct uart_port *port, struct ktermios *termios,
pmz_debug("pmz: set_termios()\n");
- if (ZS_IS_ASLEEP(uap))
- return;
-
memcpy(&uap->termios_cache, termios, sizeof(struct ktermios));
/* XXX Check which revs of machines actually allow 1 and 4Mb speeds
@@ -1605,25 +1542,34 @@ static void pmz_dispose_port(struct uart_pmac_port *uap)
*/
static int pmz_attach(struct macio_dev *mdev, const struct of_device_id *match)
{
+ struct uart_pmac_port *uap;
int i;
/* Iterate the pmz_ports array to find a matching entry
*/
for (i = 0; i < MAX_ZS_PORTS; i++)
- if (pmz_ports[i].node == mdev->ofdev.dev.of_node) {
- struct uart_pmac_port *uap = &pmz_ports[i];
-
- uap->dev = mdev;
- dev_set_drvdata(&mdev->ofdev.dev, uap);
- if (macio_request_resources(uap->dev, "pmac_zilog"))
- printk(KERN_WARNING "%s: Failed to request resource"
- ", port still active\n",
- uap->node->name);
- else
- uap->flags |= PMACZILOG_FLAG_RSRC_REQUESTED;
- return 0;
- }
- return -ENODEV;
+ if (pmz_ports[i].node == mdev->ofdev.dev.of_node)
+ break;
+ if (i >= MAX_ZS_PORTS)
+ return -ENODEV;
+
+
+ uap = &pmz_ports[i];
+ uap->dev = mdev;
+ uap->port.dev = &mdev->ofdev.dev;
+ dev_set_drvdata(&mdev->ofdev.dev, uap);
+
+ /* We still activate the port even when failing to request resources
+ * to work around bugs in ancient Apple device-trees
+ */
+ if (macio_request_resources(uap->dev, "pmac_zilog"))
+ printk(KERN_WARNING "%s: Failed to request resource"
+ ", port still active\n",
+ uap->node->name);
+ else
+ uap->flags |= PMACZILOG_FLAG_RSRC_REQUESTED;
+
+ return uart_add_one_port(&pmz_uart_reg, &uap->port);
}
/*
@@ -1637,12 +1583,15 @@ static int pmz_detach(struct macio_dev *mdev)
if (!uap)
return -ENODEV;
+ uart_remove_one_port(&pmz_uart_reg, &uap->port);
+
if (uap->flags & PMACZILOG_FLAG_RSRC_REQUESTED) {
macio_release_resources(uap->dev);
uap->flags &= ~PMACZILOG_FLAG_RSRC_REQUESTED;
}
dev_set_drvdata(&mdev->ofdev.dev, NULL);
uap->dev = NULL;
+ uap->port.dev = NULL;
return 0;
}
@@ -1651,62 +1600,13 @@ static int pmz_detach(struct macio_dev *mdev)
static int pmz_suspend(struct macio_dev *mdev, pm_message_t pm_state)
{
struct uart_pmac_port *uap = dev_get_drvdata(&mdev->ofdev.dev);
- struct uart_state *state;
- unsigned long flags;
if (uap == NULL) {
printk("HRM... pmz_suspend with NULL uap\n");
return 0;
}
- if (pm_state.event == mdev->ofdev.dev.power.power_state.event)
- return 0;
-
- pmz_debug("suspend, switching to state %d\n", pm_state.event);
-
- state = pmz_uart_reg.state + uap->port.line;
-
- mutex_lock(&pmz_irq_mutex);
- mutex_lock(&state->port.mutex);
-
- spin_lock_irqsave(&uap->port.lock, flags);
-
- if (ZS_IS_OPEN(uap) || ZS_IS_CONS(uap)) {
- /* Disable interrupt requests for the channel */
- pmz_interrupt_control(uap, 0);
-
- /* Disable receiver and transmitter */
- uap->curregs[R3] &= ~RxENABLE;
- uap->curregs[R5] &= ~TxENABLE;
-
- /* Disable break assertion */
- uap->curregs[R5] &= ~SND_BRK;
- pmz_load_zsregs(uap, uap->curregs);
-
- uap->flags |= PMACZILOG_FLAG_IS_ASLEEP;
- mb();
- }
-
- spin_unlock_irqrestore(&uap->port.lock, flags);
-
- if (ZS_IS_OPEN(uap) || ZS_IS_OPEN(uap->mate))
- if (ZS_IS_ASLEEP(uap->mate) && ZS_IS_IRQ_ON(pmz_get_port_A(uap))) {
- pmz_get_port_A(uap)->flags &= ~PMACZILOG_FLAG_IS_IRQ_ON;
- disable_irq(uap->port.irq);
- }
-
- if (ZS_IS_CONS(uap))
- uap->port.cons->flags &= ~CON_ENABLED;
-
- /* Shut the chip down */
- pmz_set_scc_power(uap, 0);
-
- mutex_unlock(&state->port.mutex);
- mutex_unlock(&pmz_irq_mutex);
-
- pmz_debug("suspend, switching complete\n");
-
- mdev->ofdev.dev.power.power_state = pm_state;
+ uart_suspend_port(&pmz_uart_reg, &uap->port);
return 0;
}
@@ -1715,74 +1615,20 @@ static int pmz_suspend(struct macio_dev *mdev, pm_message_t pm_state)
static int pmz_resume(struct macio_dev *mdev)
{
struct uart_pmac_port *uap = dev_get_drvdata(&mdev->ofdev.dev);
- struct uart_state *state;
- unsigned long flags;
- int pwr_delay = 0;
if (uap == NULL)
return 0;
- if (mdev->ofdev.dev.power.power_state.event == PM_EVENT_ON)
- return 0;
-
- pmz_debug("resume, switching to state 0\n");
-
- state = pmz_uart_reg.state + uap->port.line;
-
- mutex_lock(&pmz_irq_mutex);
- mutex_lock(&state->port.mutex);
-
- spin_lock_irqsave(&uap->port.lock, flags);
- if (!ZS_IS_OPEN(uap) && !ZS_IS_CONS(uap)) {
- spin_unlock_irqrestore(&uap->port.lock, flags);
- goto bail;
- }
- pwr_delay = __pmz_startup(uap);
-
- /* Take care of config that may have changed while asleep */
- __pmz_set_termios(&uap->port, &uap->termios_cache, NULL);
-
- spin_unlock_irqrestore(&uap->port.lock, flags);
-
- if (ZS_IS_CONS(uap))
- uap->port.cons->flags |= CON_ENABLED;
-
- /* Re-enable IRQ on the controller */
- if (ZS_IS_OPEN(uap) && !ZS_IS_IRQ_ON(pmz_get_port_A(uap))) {
- pmz_get_port_A(uap)->flags |= PMACZILOG_FLAG_IS_IRQ_ON;
- enable_irq(uap->port.irq);
- }
-
- if (ZS_IS_OPEN(uap)) {
- spin_lock_irqsave(&uap->port.lock, flags);
- pmz_interrupt_control(uap, 1);
- spin_unlock_irqrestore(&uap->port.lock, flags);
- }
-
- bail:
- mutex_unlock(&state->port.mutex);
- mutex_unlock(&pmz_irq_mutex);
-
- /* Right now, we deal with delay by blocking here, I'll be
- * smarter later on
- */
- if (pwr_delay != 0) {
- pmz_debug("pmz: delaying %d ms\n", pwr_delay);
- msleep(pwr_delay);
- }
-
- pmz_debug("resume, switching complete\n");
-
- mdev->ofdev.dev.power.power_state.event = PM_EVENT_ON;
+ uart_resume_port(&pmz_uart_reg, &uap->port);
return 0;
}
/*
* Probe all ports in the system and build the ports array, we register
- * with the serial layer at this point, the macio-type probing is only
- * used later to "attach" to the sysfs tree so we get power management
- * events
+ * with the serial layer later, so we get a proper struct device which
+ * allows the tty to attach properly. This is later than it used to be
+ * but the tty layer really wants it that way.
*/
static int __init pmz_probe(void)
{
@@ -1818,8 +1664,10 @@ static int __init pmz_probe(void)
/*
* Fill basic fields in the port structures
*/
- pmz_ports[count].mate = &pmz_ports[count+1];
- pmz_ports[count+1].mate = &pmz_ports[count];
+ if (node_b != NULL) {
+ pmz_ports[count].mate = &pmz_ports[count+1];
+ pmz_ports[count+1].mate = &pmz_ports[count];
+ }
pmz_ports[count].flags = PMACZILOG_FLAG_IS_CHANNEL_A;
pmz_ports[count].node = node_a;
pmz_ports[count+1].node = node_b;
@@ -1887,19 +1735,19 @@ static int __init pmz_probe(void)
pmz_ports_count = 0;
- pmz_ports[0].mate = &pmz_ports[1];
pmz_ports[0].port.line = 0;
pmz_ports[0].flags = PMACZILOG_FLAG_IS_CHANNEL_A;
- pmz_ports[0].node = &scc_a_pdev;
+ pmz_ports[0].pdev = &scc_a_pdev;
err = pmz_init_port(&pmz_ports[0]);
if (err)
return err;
pmz_ports_count++;
+ pmz_ports[0].mate = &pmz_ports[1];
pmz_ports[1].mate = &pmz_ports[0];
pmz_ports[1].port.line = 1;
pmz_ports[1].flags = 0;
- pmz_ports[1].node = &scc_b_pdev;
+ pmz_ports[1].pdev = &scc_b_pdev;
err = pmz_init_port(&pmz_ports[1]);
if (err)
return err;
@@ -1918,13 +1766,22 @@ static int __init pmz_attach(struct platform_device *pdev)
int i;
for (i = 0; i < pmz_ports_count; i++)
- if (pmz_ports[i].node == pdev)
- return 0;
- return -ENODEV;
+ if (pmz_ports[i].pdev == pdev)
+ break;
+ if (i >= pmz_ports_count)
+ return -ENODEV;
+
+ uap = &pmz_ports[i];
+ uap->port.dev = &pdev->dev;
+ dev_set_drvdata(&mdev->ofdev.dev, uap);
+
+ return uart_add_one_port(&pmz_uart_reg,
+ &pmz_ports[i]->port);
}
static int __exit pmz_detach(struct platform_device *pdev)
{
+ uart_remove_one_port(&pmz_uart_reg, &uap->port);
return 0;
}
@@ -1956,38 +1813,13 @@ static struct console pmz_console = {
*/
static int __init pmz_register(void)
{
- int i, rc;
-
pmz_uart_reg.nr = pmz_ports_count;
pmz_uart_reg.cons = PMACZILOG_CONSOLE;
/*
* Register this driver with the serial core
*/
- rc = uart_register_driver(&pmz_uart_reg);
- if (rc)
- return rc;
-
- /*
- * Register each port with the serial core
- */
- for (i = 0; i < pmz_ports_count; i++) {
- struct uart_pmac_port *uport = &pmz_ports[i];
- /* NULL node may happen on wallstreet */
- if (uport->node != NULL)
- rc = uart_add_one_port(&pmz_uart_reg, &uport->port);
- if (rc)
- goto err_out;
- }
-
- return 0;
-err_out:
- while (i-- > 0) {
- struct uart_pmac_port *uport = &pmz_ports[i];
- uart_remove_one_port(&pmz_uart_reg, &uport->port);
- }
- uart_unregister_driver(&pmz_uart_reg);
- return rc;
+ return uart_register_driver(&pmz_uart_reg);
}
#ifdef CONFIG_PPC_PMAC
@@ -2086,10 +1918,8 @@ static void __exit exit_pmz(void)
for (i = 0; i < pmz_ports_count; i++) {
struct uart_pmac_port *uport = &pmz_ports[i];
- if (uport->node != NULL) {
- uart_remove_one_port(&pmz_uart_reg, &uport->port);
+ if (uport->node != NULL)
pmz_dispose_port(uport);
- }
}
/* Unregister UART driver */
uart_unregister_driver(&pmz_uart_reg);
@@ -2116,8 +1946,6 @@ static void pmz_console_write(struct console *con, const char *s, unsigned int c
struct uart_pmac_port *uap = &pmz_ports[con->index];
unsigned long flags;
- if (ZS_IS_ASLEEP(uap))
- return;
spin_lock_irqsave(&uap->port.lock, flags);
/* Turn of interrupts and enable the transmitter. */
@@ -2162,8 +1990,10 @@ static int __init pmz_console_setup(struct console *co, char *options)
if (co->index >= pmz_ports_count)
co->index = 0;
uap = &pmz_ports[co->index];
+#ifdef CONFIG_PPC_PMAC
if (uap->node == NULL)
return -ENODEV;
+#endif
port = &uap->port;
/*
diff --git a/drivers/tty/serial/pmac_zilog.h b/drivers/tty/serial/pmac_zilog.h
index cbc34fb..9ae4556 100644
--- a/drivers/tty/serial/pmac_zilog.h
+++ b/drivers/tty/serial/pmac_zilog.h
@@ -2,9 +2,12 @@
#define __PMAC_ZILOG_H__
#ifdef CONFIG_PPC_PMAC
-#define pmz_debug(fmt, arg...) dev_dbg(&uap->dev->ofdev.dev, fmt, ## arg)
-#define pmz_error(fmt, arg...) dev_err(&uap->dev->ofdev.dev, fmt, ## arg)
-#define pmz_info(fmt, arg...) dev_info(&uap->dev->ofdev.dev, fmt, ## arg)
+/* We cannot use dev_* because this can be called early, way before
+ * we are matched with a device (when using it as a kernel console)
+ */
+#define pmz_debug(fmt, arg...) pr_debug("ttyPZ%d: " fmt, uap->port.line, ## arg)
+#define pmz_error(fmt, arg...) pr_err("ttyPZ%d: " fmt, uap->port.line, ## arg)
+#define pmz_info(fmt, arg...) pr_info("ttyPZ%d: " fmt, uap->port.line, ## arg)
#else
#define pmz_debug(fmt, arg...) dev_dbg(&uap->node->dev, fmt, ## arg)
#define pmz_error(fmt, arg...) dev_err(&uap->node->dev, fmt, ## arg)
@@ -35,7 +38,7 @@ struct uart_pmac_port {
*/
struct device_node *node;
#else
- struct platform_device *node;
+ struct platform_device *pdev;
#endif
/* Port type as obtained from device tree (IRDA, modem, ...) */
@@ -50,14 +53,11 @@ struct uart_pmac_port {
#define PMACZILOG_FLAG_REGS_HELD 0x00000010
#define PMACZILOG_FLAG_TX_STOPPED 0x00000020
#define PMACZILOG_FLAG_TX_ACTIVE 0x00000040
-#define PMACZILOG_FLAG_ENABLED 0x00000080
#define PMACZILOG_FLAG_IS_IRDA 0x00000100
#define PMACZILOG_FLAG_IS_INTMODEM 0x00000200
#define PMACZILOG_FLAG_HAS_DMA 0x00000400
#define PMACZILOG_FLAG_RSRC_REQUESTED 0x00000800
-#define PMACZILOG_FLAG_IS_ASLEEP 0x00001000
#define PMACZILOG_FLAG_IS_OPEN 0x00002000
-#define PMACZILOG_FLAG_IS_IRQ_ON 0x00004000
#define PMACZILOG_FLAG_IS_EXTCLK 0x00008000
#define PMACZILOG_FLAG_BREAK 0x00010000
@@ -74,6 +74,8 @@ struct uart_pmac_port {
volatile struct dbdma_regs __iomem *rx_dma_regs;
#endif
+ unsigned char irq_name[8];
+
struct ktermios termios_cache;
};
@@ -388,9 +390,7 @@ static inline void zssync(struct uart_pmac_port *port)
#define ZS_IS_IRDA(UP) ((UP)->flags & PMACZILOG_FLAG_IS_IRDA)
#define ZS_IS_INTMODEM(UP) ((UP)->flags & PMACZILOG_FLAG_IS_INTMODEM)
#define ZS_HAS_DMA(UP) ((UP)->flags & PMACZILOG_FLAG_HAS_DMA)
-#define ZS_IS_ASLEEP(UP) ((UP)->flags & PMACZILOG_FLAG_IS_ASLEEP)
#define ZS_IS_OPEN(UP) ((UP)->flags & PMACZILOG_FLAG_IS_OPEN)
-#define ZS_IS_IRQ_ON(UP) ((UP)->flags & PMACZILOG_FLAG_IS_IRQ_ON)
#define ZS_IS_EXTCLK(UP) ((UP)->flags & PMACZILOG_FLAG_IS_EXTCLK)
#endif /* __PMAC_ZILOG_H__ */
--
1.7.7.3
^ permalink raw reply related
* Perle octal serial boards
From: Philip Prindeville @ 2011-12-11 20:10 UTC (permalink / raw)
To: linux-serial
I've got a Perle Systems "Speed8 LE" board, which seems to have the Oxford Semi 954 (16PCI954 + 16PCI954N) chips on it:
$ sudo lspci -n -v -s 04:07
04:07.0 0700: 155f:b008 (prog-if 06 [16950])
Subsystem: 1415:9501
Flags: medium devsel, IRQ 21
I/O ports at ec00 [size=32]
Memory at fbfff000 (32-bit, non-prefetchable) [size=4K]
I/O ports at e880 [size=32]
Memory at fbffe000 (32-bit, non-prefetchable) [size=4K]
Capabilities: [40] Power Management version 1
04:07.1 0680: 155f:b008
Subsystem: 1415:9511
Flags: medium devsel, IRQ 10
I/O ports at e800 [size=32]
Memory at fbffd000 (32-bit, non-prefetchable) [size=4K]
I/O ports at e480 [size=32]
Memory at fbffc000 (32-bit, non-prefetchable) [size=4K]
Capabilities: [40] Power Management version 1
$
I was wondering if the 8250_pci.c driver can be made to work with it.
And if not, what's an 8-port serial PCI card that gives good performance for not a lot of money?
-Philip
^ permalink raw reply
* Re: [GIT PULL] tty-next: Fix Fsl 8250 BRK bug
From: Greg KH @ 2011-12-10 3:14 UTC (permalink / raw)
To: Paul Gortmaker
Cc: gregkh, alan, galak, linux-serial, linuxppc-dev, linux-kernel
In-Reply-To: <20111207033957.GB20556@windriver.com>
On Tue, Dec 06, 2011 at 10:39:57PM -0500, Paul Gortmaker wrote:
> Hi Greg,
>
> This is the Freescale hardware bug fix which turned into a
> six-pack of 8250 updates. This is exactly what was posted
> in the v2 review, with just Alan's ack added[1]. Since nobody
> else has had any follow-on comments since then, I'm assuming
> that it is now good to go.
>
> [1] https://lkml.org/lkml/2011/12/5/156
>
> Thanks,
> Paul.
> ---
>
> Please pull for tty-next to get:
>
> The following changes since commit 5611cc4572e889b62a7b4c72a413536bf6a9c416:
>
> Linux 3.2-rc4 (2011-12-01 14:56:01 -0800)
>
> are available in the git repository at:
> git://git.kernel.org/pub/scm/linux/kernel/git/paulg/linux fsl-uart-fix
I took the "raw" patches from the emails, so you can delete this branch
now.
thanks,
greg k-h
^ permalink raw reply
* Re: [PATCH 1/2] serial: bfin-uart: Enable hardware automatic CTS only when CTS pin is available.
From: Greg KH @ 2011-12-10 3:09 UTC (permalink / raw)
To: Sonic Zhang
Cc: Greg Kroah-Hartman, linux-serial, LKML, uclinux-dist-devel,
Sonic Zhang
In-Reply-To: <1323410421-10465-1-git-send-email-sonic.adi@gmail.com>
On Fri, Dec 09, 2011 at 02:00:20PM +0800, Sonic Zhang wrote:
> From: Sonic Zhang <sonic.zhang@analog.com>
>
> Signed-off-by: Sonic Zhang <sonic.zhang@analog.com>
> ---
> drivers/tty/serial/bfin_uart.c | 19 ++++++++++---------
> 1 files changed, 10 insertions(+), 9 deletions(-)
This patch does not apply on top of your other patches:
patching file drivers/tty/serial/bfin_uart.c
Hunk #1 FAILED at 726.
1 out of 1 hunk FAILED -- saving rejects to file drivers/tty/serial/bfin_uart.c.rej
Care to redo it on top of the next linux-next tree and resend both of
these in the series?
thanks,
greg k-h
^ permalink raw reply
* Re: [PATCH RESEND 6/8] serial: 8250: update rs485 flags with polarity settings
From: Alan Cox @ 2011-12-09 19:13 UTC (permalink / raw)
To: Wolfram Sang
Cc: linux-serial, linux-kernel, Greg KH, Alan Cox, Claudio Scordino
In-Reply-To: <1323450440-414-7-git-send-email-w.sang@pengutronix.de>
On Fri, 9 Dec 2011 18:07:18 +0100
Wolfram Sang <w.sang@pengutronix.de> wrote:
> Report the only mode we can support with the 16C850.
>
> Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
> ---
> drivers/tty/serial/8250.c | 3 +++
> 1 files changed, 3 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c
> index 28b3608..8cf6d76 100644
> --- a/drivers/tty/serial/8250.c
> +++ b/drivers/tty/serial/8250.c
> @@ -2750,6 +2750,9 @@ static int serial8250_ioctl_port(struct uart_port *port,
> serial_outp(up, UART_LCR, lcr);
> spin_unlock_irqrestore(&up->port.lock, flags);
>
> + /* only mode supported by the 16C850 */
> + rs485ctrl.flags &= ~SER_RS485_RTS_ON_SEND;
> + rs485ctrl.flags |= SER_RS485_RTS_AFTER_SEND;
> up->rs485_flags = rs485ctrl.flags;
Chip specific stuff all wants to be in a port method so while #3 sorts
out much of #2 this goes back to wanting port-> methods and flags to
avoid assumptions about chip types in the core bits.
#7 really makes the point why it is needed.
So pardon the confused series of review comments but I think the summary
is port->ops for RS485 stuff please.
^ permalink raw reply
* Re: [PATCH RESEND 3/8] serial: 8250: save rs485_flags per instance
From: Alan Cox @ 2011-12-09 19:10 UTC (permalink / raw)
To: Wolfram Sang
Cc: linux-serial, linux-kernel, Greg KH, Alan Cox, Claudio Scordino
In-Reply-To: <1323450440-414-4-git-send-email-w.sang@pengutronix.de>
On Fri, 9 Dec 2011 18:07:15 +0100
Wolfram Sang <w.sang@pengutronix.de> wrote:
> When set, save RS485 related flags in the private struct. This avoids
> mangling with chip registers when reading back the RS485 config. Also,
> features can check their configuration at runtime which will be needed
> for a later patch.
Ok thats what I get for reading in order - so the #2 problem is ok when
its folded together
^ permalink raw reply
* Re: [PATCH RESEND 2/8] serial: 8250: Add ioctl to enable auto rs485 mode with some Exar UARTs
From: Alan Cox @ 2011-12-09 19:00 UTC (permalink / raw)
To: Wolfram Sang
Cc: linux-serial, linux-kernel, Greg KH, Alan Cox, Claudio Scordino,
Matthias Fuchs
In-Reply-To: <1323450440-414-3-git-send-email-w.sang@pengutronix.de>
On Fri, 9 Dec 2011 18:07:14 +0100
Wolfram Sang <w.sang@pengutronix.de> wrote:
> From: Matthias Fuchs <mfuchs@ma-fu.de>
>
> Some Exar UARTs support an auto rs485 mode. In this mode
> the UART's RTS# pin is activated during transmitting and
> can be used to enable a rs485 line driver. This has nothing
> to do with attempts to do this by manually asserting/
> deasserting handshake lines in software.
Please split this out so that the ioctl handler calls a pair of port->
methods or errors if NULL. That'll future proof it and keep chip specific
stuff out of the direct paths.
Other than that I'm fine with it. Functionality, locking etc.
Alan
^ permalink raw reply
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