Skip to content

Commit ab28f51

Browse files
yanovichgregkh
authored andcommitted
serial: rewrite pxa2xx-uart to use 8250_core
pxa2xx-uart was a separate uart platform driver. It was declaring the same device names and numbers as 8250 driver. As a result, it was impossible to use 8250 driver on PXA SoCs. Upon closer examination pxa2xx-uart turned out to be a clone of 8250_core driver. Workaround for Erratum torvalds#19 according to Marvel(R) PXA270M Processor Specification Update (April 19, 2010) is dropped. 8250_core reads from FIFO immediately after checking DR bit in LSR. The patch leaves the original SERIAL_PXA driver around. The original driver is just marked DEPRECATED in Kconfig and C source. When the original driver is considered safe to remove, no changes to SERIAL_8250 will be necessary. Compiling SERIAL_8250_CONSOLE and SERIAL_PXA_CONSOLE even without SERIAL_8250_PXA breaks console for SERIAL_PXA. For this reasons, the new and the original drivers are made mutually exclusive. Signed-off-by: Sergei Ianovich <ynvich@gmail.com> CC: Heikki Krogerus <heikki.krogerus@linux.intel.com> CC: James Cameron <quozl@laptop.org> CC: Robert Jarzmik <robert.jarzmik@free.fr> CC: Russell King <linux@arm.linux.org.uk> Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> [rebased on v4.8] Tested-by: Robert Jarzmik <robert.jarzmik@free.fr> Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 07d9a38 commit ab28f51

File tree

6 files changed

+207
-4
lines changed

6 files changed

+207
-4
lines changed

drivers/tty/serial/8250/8250_pxa.c

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
/*
2+
* drivers/tty/serial/8250/8250_pxa.c -- driver for PXA on-board UARTS
3+
* Copyright: (C) 2013 Sergei Ianovich <ynvich@gmail.com>
4+
*
5+
* replaces drivers/serial/pxa.c by Nicolas Pitre
6+
* Created: Feb 20, 2003
7+
* Copyright: (C) 2003 Monta Vista Software, Inc.
8+
*
9+
* Based on drivers/serial/8250.c by Russell King.
10+
*
11+
* This program is free software; you can redistribute it and/or modify
12+
* it under the terms of the GNU General Public License as published by
13+
* the Free Software Foundation; either version 2 of the License, or
14+
* (at your option) any later version.
15+
*
16+
*/
17+
18+
#include <linux/device.h>
19+
#include <linux/init.h>
20+
#include <linux/io.h>
21+
#include <linux/module.h>
22+
#include <linux/serial_8250.h>
23+
#include <linux/serial_core.h>
24+
#include <linux/serial_reg.h>
25+
#include <linux/of.h>
26+
#include <linux/of_irq.h>
27+
#include <linux/of_platform.h>
28+
#include <linux/platform_device.h>
29+
#include <linux/slab.h>
30+
#include <linux/clk.h>
31+
#include <linux/pm_runtime.h>
32+
33+
#include "8250.h"
34+
35+
struct pxa8250_data {
36+
int line;
37+
struct clk *clk;
38+
};
39+
40+
#ifdef CONFIG_PM
41+
static int serial_pxa_suspend(struct device *dev)
42+
{
43+
struct pxa8250_data *data = dev_get_drvdata(dev);
44+
45+
serial8250_suspend_port(data->line);
46+
47+
return 0;
48+
}
49+
50+
static int serial_pxa_resume(struct device *dev)
51+
{
52+
struct pxa8250_data *data = dev_get_drvdata(dev);
53+
54+
serial8250_resume_port(data->line);
55+
56+
return 0;
57+
}
58+
#endif
59+
60+
static const struct dev_pm_ops serial_pxa_pm_ops = {
61+
SET_SYSTEM_SLEEP_PM_OPS(serial_pxa_suspend, serial_pxa_resume)
62+
};
63+
64+
static const struct of_device_id serial_pxa_dt_ids[] = {
65+
{ .compatible = "mrvl,pxa-uart", },
66+
{ .compatible = "mrvl,mmp-uart", },
67+
{}
68+
};
69+
MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids);
70+
71+
/* Uart divisor latch write */
72+
static void serial_pxa_dl_write(struct uart_8250_port *up, int value)
73+
{
74+
unsigned int dll;
75+
76+
serial_out(up, UART_DLL, value & 0xff);
77+
/*
78+
* work around Erratum #74 according to Marvel(R) PXA270M Processor
79+
* Specification Update (April 19, 2010)
80+
*/
81+
dll = serial_in(up, UART_DLL);
82+
WARN_ON(dll != (value & 0xff));
83+
84+
serial_out(up, UART_DLM, value >> 8 & 0xff);
85+
}
86+
87+
88+
static void serial_pxa_pm(struct uart_port *port, unsigned int state,
89+
unsigned int oldstate)
90+
{
91+
struct pxa8250_data *data = port->private_data;
92+
93+
if (!state)
94+
clk_prepare_enable(data->clk);
95+
else
96+
clk_disable_unprepare(data->clk);
97+
}
98+
99+
static int serial_pxa_probe(struct platform_device *pdev)
100+
{
101+
struct uart_8250_port uart = {};
102+
struct pxa8250_data *data;
103+
struct resource *mmres, *irqres;
104+
int ret;
105+
106+
mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
107+
irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
108+
if (!mmres || !irqres)
109+
return -ENODEV;
110+
111+
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
112+
if (!data)
113+
return -ENOMEM;
114+
115+
data->clk = devm_clk_get(&pdev->dev, NULL);
116+
if (IS_ERR(data->clk))
117+
return PTR_ERR(data->clk);
118+
119+
ret = clk_prepare(data->clk);
120+
if (ret)
121+
return ret;
122+
123+
uart.port.type = PORT_XSCALE;
124+
uart.port.iotype = UPIO_MEM32;
125+
uart.port.mapbase = mmres->start;
126+
uart.port.regshift = 2;
127+
uart.port.irq = irqres->start;
128+
uart.port.fifosize = 64;
129+
uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST;
130+
uart.port.dev = &pdev->dev;
131+
uart.port.uartclk = clk_get_rate(data->clk);
132+
uart.port.pm = serial_pxa_pm;
133+
uart.port.private_data = data;
134+
uart.dl_write = serial_pxa_dl_write;
135+
136+
ret = serial8250_register_8250_port(&uart);
137+
if (ret < 0)
138+
goto err_clk;
139+
140+
data->line = ret;
141+
142+
platform_set_drvdata(pdev, data);
143+
144+
return 0;
145+
146+
err_clk:
147+
clk_unprepare(data->clk);
148+
return ret;
149+
}
150+
151+
static int serial_pxa_remove(struct platform_device *pdev)
152+
{
153+
struct pxa8250_data *data = platform_get_drvdata(pdev);
154+
155+
serial8250_unregister_port(data->line);
156+
157+
clk_unprepare(data->clk);
158+
159+
return 0;
160+
}
161+
162+
static struct platform_driver serial_pxa_driver = {
163+
.probe = serial_pxa_probe,
164+
.remove = serial_pxa_remove,
165+
166+
.driver = {
167+
.name = "pxa2xx-uart",
168+
.pm = &serial_pxa_pm_ops,
169+
.of_match_table = serial_pxa_dt_ids,
170+
},
171+
};
172+
173+
module_platform_driver(serial_pxa_driver);
174+
175+
MODULE_AUTHOR("Sergei Ianovich");
176+
MODULE_LICENSE("GPL");
177+
MODULE_ALIAS("platform:pxa2xx-uart");

drivers/tty/serial/8250/Kconfig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,16 @@ config SERIAL_8250_MOXA
439439
This driver can also be built as a module. The module will be called
440440
8250_moxa. If you want to do that, say M here.
441441

442+
config SERIAL_8250_PXA
443+
tristate "PXA serial port support"
444+
depends on SERIAL_8250
445+
depends on ARCH_PXA || ARCH_MMP
446+
help
447+
If you have a machine based on an Intel XScale PXA2xx CPU you can
448+
enable its onboard serial ports by enabling this option. The option is
449+
applicable to both devicetree and legacy boards, and early console is
450+
part of its support.
451+
442452
config SERIAL_OF_PLATFORM
443453
tristate "Devicetree based probing for 8250 ports"
444454
depends on SERIAL_8250 && OF

drivers/tty/serial/8250/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ obj-$(CONFIG_SERIAL_8250_INGENIC) += 8250_ingenic.o
3131
obj-$(CONFIG_SERIAL_8250_LPSS) += 8250_lpss.o
3232
obj-$(CONFIG_SERIAL_8250_MID) += 8250_mid.o
3333
obj-$(CONFIG_SERIAL_8250_MOXA) += 8250_moxa.o
34+
obj-$(CONFIG_SERIAL_8250_PXA) += 8250_pxa.o
3435
obj-$(CONFIG_SERIAL_OF_PLATFORM) += 8250_of.o
3536

3637
CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt

drivers/tty/serial/Kconfig

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -438,17 +438,27 @@ config SERIAL_MPSC_CONSOLE
438438
Say Y here if you want to support a serial console on a Marvell MPSC.
439439

440440
config SERIAL_PXA
441-
bool "PXA serial port support"
441+
bool "PXA serial port support (DEPRECATED)"
442442
depends on ARCH_PXA || ARCH_MMP
443443
select SERIAL_CORE
444+
select SERIAL_8250_PXA if SERIAL_8250=y
445+
select SERIAL_PXA_NON8250 if !SERIAL_8250=y
444446
help
445447
If you have a machine based on an Intel XScale PXA2xx CPU you
446448
can enable its onboard serial ports by enabling this option.
447449

450+
Unless you have a specific need, you should use SERIAL_8250_PXA
451+
instead of this.
452+
453+
config SERIAL_PXA_NON8250
454+
bool
455+
depends on !SERIAL_8250
456+
448457
config SERIAL_PXA_CONSOLE
449-
bool "Console on PXA serial port"
458+
bool "Console on PXA serial port (DEPRECATED)"
450459
depends on SERIAL_PXA
451460
select SERIAL_CORE_CONSOLE
461+
select SERIAL_8250_CONSOLE if SERIAL_8250=y
452462
help
453463
If you have enabled the serial port on the Intel XScale PXA
454464
CPU you can make it the console by answering Y to this option.
@@ -460,6 +470,9 @@ config SERIAL_PXA_CONSOLE
460470
your boot loader (lilo or loadlin) about how to pass options to the
461471
kernel at boot time.)
462472

473+
Unless you have a specific need, you should use SERIAL_8250_PXA
474+
and SERIAL_8250_CONSOLE instead of this.
475+
463476
config SERIAL_SA1100
464477
bool "SA1100 serial port support"
465478
depends on ARCH_SA1100

drivers/tty/serial/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ obj-$(CONFIG_SERIAL_8250) += 8250/
2323
obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
2424
obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
2525
obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
26-
obj-$(CONFIG_SERIAL_PXA) += pxa.o
26+
obj-$(CONFIG_SERIAL_PXA_NON8250) += pxa.o
2727
obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
2828
obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
2929
obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o

drivers/tty/serial/pxa.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -925,7 +925,9 @@ static struct platform_driver serial_pxa_driver = {
925925
},
926926
};
927927

928-
static int __init serial_pxa_init(void)
928+
929+
/* 8250 driver for PXA serial ports should be used */
930+
static int __deprecated __init serial_pxa_init(void)
929931
{
930932
int ret;
931933

0 commit comments

Comments
 (0)